观察者模式

一个简单的例子,比如说猫叫,老鼠跑,主人被惊醒。

在不知道观察者模式之前,我们的代码可能是这样的。

[c-sharp]  view plain copy
  1. //老鼠类  
  2.  class Mouse   
  3.  {  
  4.      public void Run()   
  5.      {  
  6.          Console.WriteLine("老鼠跑了!");  
  7.      }  
  8.  }  
  9.   
  10.  //主人类  
  11.  class Master   
  12.  {  
  13.      public void Wake()  
  14.      {  
  15.          Console.WriteLine("主人醒了!");  
  16.      }  
  17.  }  
  18.   
  19.  //猫类  
  20.  class Cat   
  21.  {  
  22.      public void Cry ()  
  23.      {  
  24.          Console.WriteLine("猫叫了!");  
  25.          new Mouse().Run();//猫叫的同时,调用老鼠跑的方法。  
  26.          new Master().Wake();//猫叫的同时,调用主人醒的方法。  
  27.      }  
  28.  }  
  29.   
  30.  class Program  
  31.  {  
  32.      static void Main(string[] args)  
  33.      {  
  34.          Cat cat = new Cat();  
  35.          cat.Cry();  
  36.   
  37.          Console.ReadLine();  
  38.      }  
  39.  }  

这个代码基本上能实现所有的功能。但是,这个方法特别不利用扩展,

试想,如果,猫叫后,狗也叫,那是不是也要在猫叫的方法里重新加入狗叫的方法?

或者说,猫叫后,主人他老婆也醒了,是不是也要在猫叫的方法里加入他老婆醒的方法呢?

显然,这样的代码不利用维护,也不是面向对象的代码。


观察者模式能够很好的解决这个问题。

观察者模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都得到通知并自动更新。在我们的例子中,猫和老鼠,主人,狗,主人他老婆是一对多的依赖,当猫叫时,所有依赖于它的对象都会自动执行某个操作。

 

观察者模式的实现,一般有下面四部分组成。

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接口:

  1. interface ISubject  
  2.     {  
  3.         void Notify();//主题变动时,通知虽有观察者  
  4.         void Regiester(IObservable o);//观察者注册  
  5.         void UnRegiester(IObservable o);//观察者取消注册,此时主题发生任何变动,观察者都不会得到通知。  
  6.     }  

2.Subject 类:

  1. class Cat : ISubject  
  2.    {  
  3.        private IList<IObservable> observers = new List<IObservable>();  
  4.   
  5.        public void Notify()  
  6.        {  
  7.            foreach (IObservable o in observers) //逐个通知观察者  
  8.            {  
  9.                o.Action();  
  10.            }  
  11.        }  
  12.   
  13.        public void Regiester(IObservable o)  
  14.        {  
  15.            if (o != null || !observers.Contains(o))  
  16.            {  
  17.                observers.Add(o);  
  18.            }  
  19.        }  
  20.   
  21.        public void UnRegiester(IObservable o)  
  22.        {  
  23.            if (observers != null && observers.Contains(o))  
  24.            {  
  25.                observers.Remove(o);  
  26.            }  
  27.        }  
  28.   
  29.        public void Cry()  
  30.        {  
  31.            Console.WriteLine("猫叫了!");  
  32.            Notify();  
  33.        }  
  34.    } 

3. IObservable 接口:

  1. interface IObservable  
  2. {  
  3.     void Action();//观察者对主题变动所对应的操作  
  4. }  

4.Observer类(2个,Mouse和Master)

  1. class Mouse : IObservable  
  2.    {  
  3.        public void Action()  
  4.        {  
  5.            Console.WriteLine("鼠跑了!");  
  6.        }  
  7.    }  
  8.   
  9.    class Master : IObservable  
  10.    {  
  11.        public void Action()  
  12.        {  
  13.            Console.WriteLine("主人醒了!");  
  14.        }  
  15.    } 

5.主程序

  1.            Mouse mouse = new Mouse();  
  2.            Master master = new Master();  
  3.            Cat cat = new Cat();  
  4.   
  5.            cat.Regiester(mouse);  
  6.            cat.Regiester(master);  
  7.   
  8.            cat.Cry();  
  9.   
  10.            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();
        }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值