设计模式——观察者模式

Posted 勤学才是王道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式——观察者模式相关的知识,希望对你有一定的参考价值。

 

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

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

 

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

 

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

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

 

 

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

以上是关于设计模式——观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式补充:回调模式事件监听器模式观察者模式(转)

设计模式观察者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

观察者模式

未调用 LiveData 观察者

设计模式之美(c++)-笔记-56-观察者模式

设计模式之美(c++)-笔记-56-观察者模式