设计模式设计模式:Observer(观察器)(观察器)
本页内容本页内容
上下文
问题
影响因素
解决方案
示例
结果上下文
相关模式
上下文上下文
在面向对象的编程中,对象同时包含数据和行为,这两者一起表示业务域的特定方面。使用对象生成应用程序的优点之一是可
以将所有数据操作封装在对象内。这样,就使对象成为独立的单位,并增加了在其他应用程序中重用对象的可能性。但是,对
象无法在孤立状态下工作。在除最不重要的应用程序之外的所有应用程序中,对象必须协作才能完成更复杂的任务。当对象协
作时,对象可能必须在对象状态发生更改时互相通知对方。例如,Model-View-Controller 模式规定将业务数据(模型)与显
示逻辑(视图)分离。当模型发生改变时,系统必须通知视图以便它可以刷新可视显示,并准确地反映模型的状态。换句话
说,视图依赖于模型,以便获知模型内部状态的更改。
返回页首
问题问题
一个对象如何将状态更改通知其他对象,而又不依赖于这些对象的类?
返回页首
影响因素影响因素
要解决此问题,就必须协调下列影响因素和注意事项:
将状态更改通知依赖对象的最容易的方法是直接调用它们。但是,对象之间的直接协作需要让它们的类建立相互的依赖
性。例如,如果模型对象调用视图对象以便将更改通知它,则模型类现在也会依赖于视图类。两个对象之间的这种直接
耦合(也称为紧耦合)降低了类的可重用性。例如,每当要重用模型类时,还必须重用视图类,因为模型会调用它。如
果有多个视图,问题就更复杂了。
在事件驱动的框架中,经常出现需要耦合类的情况。框架必须能够将事件通知应用程序,但是框架不能依赖于特定应用
程序类。
同样,如果对视图类进行了更改,则模型很可能受到影响。包含许多紧耦合类的应用程序往往是脆弱的和难于维护的,
因为一个类中的更改可能影响所有的紧耦合类。
如果直接调用依赖对象,则在每次添加新依赖项时,都必须对源对象内的代码进行修改。
在某些情况下,依赖性对象的数目在设计时可能是未知的。例如,如果您允许用户打开某个特定模型的多个窗口(视
图),则必须在模型状态改变时更新多个视图。
直接的函数调用仍然是在两个对象之间传递信息时效率最高的方式(仅次于让两个对象的功能同时包含在同一个对象
中)。因此,使用其他机制将对象功能分隔开来很可能对性能有负面影响。取决于应用程序的性能要求,您可能必须对
此进行权衡。
返回页首
解决方案解决方案
使用 Observer 模式在独立的对象(主体)中维护一个对主体感兴趣的依赖项(观察器)列表。让所有观察器各自实现公共的
Observer 接口,以取消主体和依赖性对象之间的直接依赖关系(见图 1)。
同样,如果对视图类进行了更改,则模型很可能受到影响。包含许多紧耦合类的应用程序往往是脆弱的和难于维护的,因为一
个类中的更改可能影响所有的紧耦合类。
图 1:
基本的
Observer
结构