一个简单的例子,比如说猫叫,老鼠跑,主人被惊醒。
在不知道观察者模式之前,我们的代码可能是这样的。
- //老鼠类
- class Mouse
- {
- public void Run()
- {
- Console.WriteLine("老鼠跑了!");
- }
- }
- //主人类
- class Master
- {
- public void Wake()
- {
- Console.WriteLine("主人醒了!");
- }
- }
- //猫类
- class Cat
- {
- public void Cry ()
- {
- Console.WriteLine("猫叫了!");
- new Mouse().Run();//猫叫的同时,调用老鼠跑的方法。
- new Master().Wake();//猫叫的同时,调用主人醒的方法。
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Cat cat = new Cat();
- cat.Cry();
- Console.ReadLine();
- }
- }
这个代码基本上能实现所有的功能。但是,这个方法特别不利用扩展,
试想,如果,猫叫后,狗也叫,那是不是也要在猫叫的方法里重新加入狗叫的方法?
或者说,猫叫后,主人他老婆也醒了,是不是也要在猫叫的方法里加入他老婆醒的方法呢?
显然,这样的代码不利用维护,也不是面向对象的代码。
观察者模式能够很好的解决这个问题。
观察者模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并自动更新。在我们的例子中,猫和老鼠,主人,狗,主人他老婆是一对多的依赖,当猫叫时,所有依赖于它的对象都会自动执行某个操作。
观察者模式的实现,一般有下面四部分组成。
1.ISubject接口(抽象目标),含方法Notify,Register,UnRegister(名字可以自己任意取名)
2.Subject类(实体目标),实现ISubject接口,一般只有一个
3.IObservable接口(抽象观察者)。
4 Observer类(实体观察者),实现IObservable接口,一般有多个。
观察者模式中的“注册--通知--注销”图示:
1. 观察者(Observer)将自己(Regiester)注册到被观察对象(Subject)中,被观察对象将观察者放在一个容器(Container)。Container一般为Ilist,Arraylist等数据结构,存放多个IObservable接口变量。
2.当被观察对象(Subject)发生变化(如图中的AskPriceChanged)时,容器(Container)中的所有观察者(Observer)都得到通知(Notify 方法),此时观察者会自动执行某些方法。
3.当观察者不想继续观察被观察者时,可以注销(UnRegiester方法)
上面的例子中改造后变成:
1.ISubject接口:
- interface ISubject
- {
- void Notify();//主题变动时,通知虽有观察者
- void Regiester(IObservable o);//观察者注册
- void UnRegiester(IObservable o);//观察者取消注册,此时主题发生任何变动,观察者都不会得到通知。
- }
2.Subject 类:
- class Cat : ISubject
- {
- private IList<IObservable> observers = new List<IObservable>();
- public void Notify()
- {
- foreach (IObservable o in observers) //逐个通知观察者
- {
- o.Action();
- }
- }
- public void Regiester(IObservable o)
- {
- if (o != null || !observers.Contains(o))
- {
- observers.Add(o);
- }
- }
- public void UnRegiester(IObservable o)
- {
- if (observers != null && observers.Contains(o))
- {
- observers.Remove(o);
- }
- }
- public void Cry()
- {
- Console.WriteLine("猫叫了!");
- Notify();
- }
- }
3. IObservable 接口:
- interface IObservable
- {
- void Action();//观察者对主题变动所对应的操作
- }
4.Observer类(2个,Mouse和Master)
- class Mouse : IObservable
- {
- public void Action()
- {
- Console.WriteLine("鼠跑了!");
- }
- }
- class Master : IObservable
- {
- public void Action()
- {
- Console.WriteLine("主人醒了!");
- }
- }
5.主程序
- Mouse mouse = new Mouse();
- Master master = new Master();
- Cat cat = new Cat();
- cat.Regiester(mouse);
- cat.Regiester(master);
- cat.Cry();
- Console.ReadLine();
这样就实现了观察者模式,通过把依赖类注册到主体类中,当主体类发生变化时,所有依赖类都得到了通知。如果需要扩展,比如说象上面例子的狗也叫了,我们可以定义一个狗类,然后在主程序中把狗对象注册到猫类中就可以了。如果不想依赖于猫类,也可以通过UnRegiester方法取消绑定。
另外一种实现方法:
namespace ConsoleTest.MouseAndCat { public delegate void Delegate(); }

public abstract class Subject { public event Delegate Eventhandler; public void FireAway() { if (this.Eventhandler != null) { this.Eventhandler(); } } } public class Cat:Subject { public void Cry() { this.FireAway(); } } public class Dog:Subject { public void Cry() { this.FireAway(); } }

public abstract class Observer { public Observer(Subject sub) { sub.Eventhandler += new Delegate(Action); } public abstract void Action(); } public class Master:Observer { public Master(Subject sub):base(sub) { } public override void Action() { Console.WriteLine("主人听见了!"); } } public class Mouse:Observer { public Mouse(Subject sub): base(sub) {} public override void Action() { Console.WriteLine("老鼠听见了,逃跑!"); } }

static void Main(string[] args) { Cat cat = new Cat(); Mouse mouse = new Mouse(cat); Master master = new Master(cat); cat.Cry(); Dog dog = new Dog(); Mouse dog_mouse = new Mouse(dog); Master dog_master = new Master(dog); dog.Cry(); Console.ReadKey(); }