模式说明
观察者模式是作者接触的比较早的设计模式,也是作者比较早理解的设计模式。该模式属与行为模式。该模式也叫依赖(Dependents),发布-订阅(publish-Subscribe)
意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
GOF,设计模式:可复用面向对象软件的基础
别名
依赖(Dependents),发布-订阅(publish-Subscribe)
适用性
- 当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。【这条博主也不是很理解。】
- 当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变。
- 当一个对象必须通知其他对象。而它又不能假定其他对象是谁。换言之,你不希望这些对象是紧密耦合的。
结构
参与者
Subject(目标)
- 目标知道它的观察者,可以有人以多个个观察者观察同一个目标。
- 提供注册和删除观察者对象的接口
Observer(观察者)
- 为那些在目标发生改变时需要获取通知的对象定义一个接口。
ConcreteSubject(具体的目标)
- 将有关状态存入各ConcreteObserver对象
- 当它的状态发生改变,向他的各个观察者发出通知。
ConcreteObserver
- 维护一个指向ConcreteSubject对象的引用。
- 存储有关状态,这些状态应与目标对象的状态保持一致。
- 实现Observer的更新接口以使自身的状态与目标的状态保持一致。
模式实战
小张开了一家饭店。饭店的菜单会经常发生变化,菜单变化的时候,小张要通知采购部的相关人员。对菜品进行采购。当然最好通知经常来吃饭的客户。
这个场景非常符合我们观察者模式,当菜单变化的时候要通知客户和采购部门。观察者的数量不确定,类型也不确定。将来可能也会有其他类型的观察者。
我们先定义主题接口和具体的饭店菜单主题
|
|
然后我们定义具体观察者接口和相关的观察者
|
|
创建WINFROM项目为实现客户端代码。当我们改变菜单,点击确定按钮时。所有的观察者都得到了更新。
|
|
程序的界面如下
基本的功能都实现了,动态的添加、删除观察者。菜单改变,改变后用户观察者得到的消息展示。如果先查看代码传送门,做之前想要做的多少多好,每次一开始写,就写的很差劲了。多练吧。
效果及实现要点
推拉模式
推模型:目标想所有的观察者发送改变的详细信息。不管观察者是否需要。
缺点:目标知道观察者需要的信息。所以目标难以复用。
拉模型:目标不主动推送改变的数据,由观察者得到更新通知后,显示访问目标对象。
缺点:效率较差,因为目标更改了那些内容需要观察者自己去获取。
.NET EVEN与观察者模式接口
- 在C#语言中从语言层面已经实现了观察者模式,那就是事件和委托。而且事件和委托比观察者的模型更灵活。
- System.IObservable
.aspx) 和 System.IObserver .aspx) 接口 ,.NET4.0自带了对观察者实现的泛型接口。提供的接口与传统的观察者模不同,但是目的是一样的。传送门.aspx)
显示的制定感兴趣的改变
当只对主题的特定数据和事件感兴趣的时候,可以注册对主题感兴趣的方面(aspects),主题在执行更新操作的时候将这一方面的改变发送给订阅者。接口如下,目前我对方面的认识还不够,但是我认为这个是非常有意义的。当我们只对菜单的某一个菜感兴趣时或者我们只对周五菜单改变刚兴趣这种接口就比较有威力了。书中的定义如下。
|
|
###
模式总结
通过Observer模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。
参考资料
MSDN WebCast 《C#面向对象设计模式纵横谈(19):Observer 观察者模式(行为型模式)》
Erich Gamma等,《设计模式:可复用面向对象软件的基础》
()