设计模式——观察者模式
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设计模式补充:回调模式事件监听器模式观察者模式(转)