• 设计模式——观察者模式


    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    这种交互方式也被叫做发布—订阅

    观察者模式中关键的对象是目标和观察者。

    一个目标可以由任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的相应,每个观察者都查询目标以使其状态与目标状态同步。

    目标发布事件,观察者订阅事件。被观察者不需要知道是谁订阅了事件,可以有任意数目的观察者订阅事件。

    Subject( 目标)

    ——目标知道它的观察者,可以有任意多个观察者观察目标

    ——提供注册和删除观察者对象的接口

    Observe(观察者)

    ——为那些目标状态改变需要获得通知的对象定义一个更新接口

    ConcreteSubject(具体目标)

    ——将有关状态存入各ConcreteObserve对象

    ——当它的状态改变时,向它的各个观察者发出通知

    ConcreteObserve(具体观察者)

    ——维护一个指向ConcreteSubject对象的引用

    ——储存有关状态,这些状体与目标的状态保持一致

    ——实现Observe的更新接口以使自身的状态与目标状态保持一致

    题目:猫大叫,两只老鼠开始逃跑,主人醒来,宝宝也醒来了并且哭了起来

    猫是目标由于它的某些动作才导致了以后的一系列事情发生

    C#语言使用委托以及事件,可以很好的实现观察者模式

    目标的基类

     1         /**//// <summary>
     2 
     3     ///     在Observer Pattern(观察者模式)中,此类作为所有Subject(目标)的抽象基类
     4 
     5     /// 所有要充当Subject的类(在此事例中为"猫")都继承于此类.
     6 
     7     ///     我们说此类作为模型,用于规划目标(即发布方)所产生的事件,及提供触发
     8 
     9     /// 事件的方法.
    10 
    11     ///     此抽象类无抽象方法,主要是为了不能实例化该类对象,确保模式完整性.
    12 
    13     ///     具体实施:
    14 
    15     ///     1.声明委托
    16 
    17     ///     2.声明委托类型事件
    18 
    19     ///     3.提供触发事件的方法
    20 
    21     /// </summary>
    22 
    23     public abstract class ModelBase
    24 
    25     {
    26 
    27         public ModelBase()
    28 
    29         {
    30 
    31         }
    32 
    33         /**//// <summary>
    34 
    35         /// 声明一个委托,用于代理一系列"无返回"及"不带参"的自定义方法
    36 
    37         /// </summary>
    38 
    39         public delegate void SubEventHandler(); 
    40 
    41         /**//// <summary>
    42 
    43         /// 声明一个绑定于上行所定义的委托的事件
    44 
    45         /// </summary>
    46 
    47         public event SubEventHandler SubEvent;
    48  
    49 
    50         /**//// <summary>
    51 
    52         /// 封装了触发事件的方法
    53 
    54         /// 主要为了规范化及安全性,除观察者基类外,其派生类不直接触发委托事件
    55 
    56         /// </summary>
    57 
    58         protected void Notify()
    59         {
    60 
    61             //提高执行效率及安全性
    62 
    63             if(this.SubEvent!=null)
    64 
    65                 this.SubEvent();
    66         }
    67 
    68     }

    只完成一个动作观察者基类

     1    /**/
     2     /// <summary>
     3 
     4     ///     在Observer Pattern(观察者模式)中,此类作为所有Observer(观察者)的抽象基类
     5 
     6     /// 所有要充当观察者的类(在此事例中为"老鼠"和"人")都继承于此类.
     7 
     8     ///     我们说此类作为观察者基类,用于规划所有观察者(即订阅方)订阅行为.
     9 
    10     ///     在此事例中,规划了针对目标基类(ModelBase)中声明的"无参无返回"委托的一个
    11 
    12     /// 方法(Response),并于构造该观察者时将其注册于具体目标(参数传递)的委托事件中.
    13 
    14     ///     具体实施过程:
    15 
    16     ///     1.指定观察者所观察的对象(即发布方).(通过构造器传递)
    17 
    18     ///     2.规划观察者自身需要作出响应方法列表
    19 
    20     ///     3.注册需要委托执行的方法.(通过构造器实现)
    21 
    22     /// </summary>
    23     /// 
    24     abstract class Observer
    25     {
    26 
    27         /**//// <summary>
    28 
    29         /// 构造时通过传入模型对象,把观察者与模型关联,并完成订阅.    -单行为-
    30 
    31         /// 在此确定需要观察的模型对象.
    32 
    33         /// </summary>
    34 
    35         /// <param name="childModel">需要观察的对象</param>
    36 
    37         public Observer(ModelBase childModel)
    38 
    39         {
    40 
    41             //订阅
    42 
    43             //把观察者行为(这里是Response)注册于委托事件
    44 
    45             childModel.SubEvent+=new ModelBase.SubEventHandler(Response);
    46 
    47         }
    48 
    49  
    50 
    51         /**//// <summary>
    52 
    53         /// 规划了观察者的一种行为(方法),所有派生于该观察者基类的具体观察者都
    54 
    55         /// 通过覆盖该方法来实现作出响应的行为.
    56 
    57         /// </summary>
    58 
    59         public abstract void Response();
    60     }

    需完成两个动作的观察者基类

     1          /**//// <summary>
     2  
     3      /// 定义了另一个观察者基类.该观察者类型拥有两个响应行为.
     4 
     5     /// 并在构造时将响应行为注册于委托事件.
     6 
     7     /// (具体描述请参照另一观察者基类Observer)
     8 
     9     /// </summary>
    10     abstract class Observer2
    11     {
    12          /**//// <summary>
    13 
    14         /// 构造时通过传入模型对象,把观察者与模型关联,并完成订阅.
    15 
    16         /// 在此确定需要观察的模型对象.
    17 
    18         /// </summary>
    19 
    20         /// <param name="childModel">需要观察的对象</param>
    21         /// 
    22 
    23 
    24           public Observer2(ModelBase childModel)
    25 
    26         {
    27 
    28             //订阅
    29 
    30             //把观察者行为(这里是Response和Response2)注册于委托事件
    31 
    32             childModel.SubEvent+=new ModelBase.SubEventHandler(Response);
    33 
    34             childModel.SubEvent+=new ModelBase.SubEventHandler(Response2);
    35 
    36             
    37 
    38         }
    39 
    40         /**//// <summary>
    41 
    42         /// 规划了观察者的二种行为(方法),所有派生于该观察者基类的具体观察者都
    43 
    44         /// 通过覆盖该方法来实现作出响应的行为.
    45 
    46         /// </summary>
    47 
    48         public abstract void Response();
    49 
    50         public abstract void Response2();
    51     }

    实现目标类:猫

     1     /**//// <summary>
     2  
     3      ///     此类为观察者模式中的具体目标(即具体发布方),其继承于模型.
     4 
     5     /// 其中包含(调用)了在模型中被封装好的触发委托事件的方法.
     6 
     7     /// </summary>
     8     class Cat:ModelBase
     9     {
    10          public Cat()
    11 
    12         {
    13 
    14         }
    15 
    16         /**//// <summary>
    17 
    18         /// 定义了猫的一种行为----大叫
    19 
    20         /// </summary>
    21 
    22         public void Cry()
    23 
    24         {
    25 
    26             System.Console.WriteLine("Cat Cry..");
    27 
    28             //调用了触发委托事件的方法.
    29 
    30             //通知委托开始执行观察者已订阅的方法.
    31 
    32             this.Notify();  
    33 
    34          }
    35     }

    实现观察者:老鼠

     1       /**//// <summary>
     2 
     3     ///     此类为观察者模式中的具体观察者(即具体发布方),其继承于观察者基类.
     4 
     5     /// 其中覆盖了观察者基类规划好的方法,实现了响应的具体行为.
     6 
     7     /// </summary>
     8     class Mouse:Observer
     9     {
    10 
    11         /**//// <summary>
    12 
    13         /// 观察者可以拥有自己的成员(字段或者方法).
    14 
    15         /// 在此事例中增加了"老鼠的名字"
    16 
    17         /// </summary>
    18 
    19         private string name;
    20 
    21         /**//// <summary>
    22 
    23         ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,
    24 
    25         /// 实现响应行为(方法)的订阅.另外,为观察者实例初始化成员.
    26 
    27         /// </summary>
    28 
    29         /// <param name="name">老鼠的名字</param>
    30 
    31         /// <param name="childModel">
    32 
    33         ///     需要观察的对象(发布方).
    34 
    35         ///     此处用模型基类来传递,是为了兼容所有派生于此模型的观察者,从而提高扩展性.
    36 
    37         /// </param>
    38 
    39         public Mouse(string name,ModelBase childModel):base(childModel)
    40 
    41         {
    42 
    43             //初始化字段(老鼠的名字)
    44 
    45             this.name=name;         
    46 
    47         }
    48 
    49         /**//// <summary>
    50 
    51         /// 覆盖了该类观察者需要作出的具体响应行为.
    52 
    53         /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.
    54 
    55         /// </summary>
    56 
    57         public override void Response()
    58 
    59         {
    60 
    61             //具体响应内容
    62 
    63             System.Console.WriteLine(this.name+"开始逃跑");
    64 
    65         }
    66     }

    实现观察者:主人

     1      /**//// <summary>
     2  
     3      ///     此类为观察者模式中的具体观察者(即具体发布方),其继承于观察者基类.
     4 
     5     /// 其中覆盖了观察者基类规划好的方法,实现了响应的具体行为.
     6 
     7     /// </summary>
     8     class Master:Observer
     9     {
    10           /**//// <summary>
    11 
    12         ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,
    13 
    14         /// 实现响应行为(方法)的订阅.
    15 
    16         /// </summary>
    17 
    18         public Master(ModelBase childModel):base(childModel)
    19 
    20         {
    21 
    22         }
    23 
    24  
    25 
    26         /**//// <summary>
    27 
    28         /// 覆盖了该类观察者需要作出的具体响应行为.
    29 
    30         /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.
    31 
    32         /// </summary>
    33 
    34         public override void Response()
    35 
    36         {
    37 
    38             System.Console.WriteLine("主人醒来");
    39 
    40         }
    41     }

    实现观察者:小主人

     1     /**//// <summary>
     2 
     3     ///     此类为观察者模式中的具体观察者(即具体发布方),其继承了订阅了2个响应行为的
     4 
     5     /// 观察者基类.
     6 
     7     ///     其中覆盖了观察者基类规划好的二个方法,实现了响应的具体行为.
     8 
     9     /// </summary>
    10     class Master2:Observer2
    11     {
    12         /**//// <summary>
    13 
    14         ///     构造时确定观察者所需要观察的对象(具体目标),并传递给观察者基类构造器,
    15 
    16         /// 实现响应行为(方法)的订阅.
    17 
    18         /// </summary>
    19 
    20         public Master2(ModelBase childBase):base(childBase)
    21 
    22         {
    23 
    24         }
    25 
    26  
    27 
    28         /**//// <summary>
    29 
    30         /// 覆盖了该类观察者需要作出的具体响应行为.
    31 
    32         /// 此行为已在观察者基类中注册于委托事件,由委托事件调度执行,不需要直接调用.
    33 
    34         /// </summary>
    35 
    36         public override void Response()
    37 
    38         {
    39 
    40             Console.WriteLine("baby醒来。。。。");
    41 
    42  
    43 
    44         }
    45 
    46         /**//// <summary>
    47 
    48         /// 覆盖了该类观察者需要作出的另一个响应行为.
    49 
    50         /// </summary>
    51 
    52         public override void Response2()
    53 
    54         {
    55 
    56             Console.WriteLine("开始哭闹。。。。。");
    57 
    58         }
    59     }

    具体调用:

     1   //声明并实例化一个目标(即发布方)对象----猫
     2 
     3             Cat myCat=new Cat();
     4 
     5             //声明并实例化一个Mouse类型的观察者对象--名叫mouse1的老鼠.并把那只猫作为它所要观察的对象.
     6 
     7             Mouse myMouse1=new Mouse("mouse1",myCat);
     8 
     9             //类似地生成另一只名叫mouse2的老鼠(观察者),把同一只猫作为它的观察的对象.
    10 
    11             Mouse myMouse2=new Mouse("mouse2",myCat);
    12 
    13             //声明并实例化一个Master类型的观察者--主人,并同时把那只猫也作为他的观察对象.
    14 
    15             Master myMaster=new Master(myCat);
    16 
    17             //声明并实例化一个Master2类型的观察者--宝宝,同时把那只猫也
    18 
    19             Master2 myLittleMaster=new Master2(myCat);
    20 
    21  
    22 
    23             //猫大叫,并触发了委托事件,从而开始按顺序调用观察者已订阅的方法.
    24 
    25             myCat.Cry();
    26 
    27  
    28 
    29             Console.Read();

    学习于     https://www.cnblogs.com/promise-7/archive/2012/05/14/2500759.html

  • 相关阅读:
    关于session的记录
    关于<input type="hidden"/>标签的记录
    H3C S5120V2-SI 交换机配置
    Windows 系列GVLK密钥
    给因特尔S2600CO服务器主板安装【SAS控制器】驱动
    EMQ消息队列初体验
    泰国佛历的换算问题
    linux下批量查找UTF-8的BOM文件,并去除BOM
    菲律宾Globe/TM卡最省钱的上网方案
    Windows计划任务实现MYSQL冷备份
  • 原文地址:https://www.cnblogs.com/cwmizlp/p/9068228.html
Copyright © 2020-2023  润新知