2005年3月4日星期五

《ASD》设计模式:Observer

Observer模式稍稍有点复杂,但是由于他的作用如此强大,所以几乎在所有的带有分层概念的系统中都必须使用。
带有GUI的软件几乎都有分层的概念,界面是一层,逻辑实现是一层。所以他们也就成了最常见的Observer模式的例子。
不过Observer模式的用处要比单纯的GUI要宽广很多。Observer的应用环境是,有上下两层模块,下层模块的数据会自发变化,上层模块必须响应这样的变化,但是上层模块不知道下层模块会在什么时候变化。这种情况下就应该使用Observer模式,上层模块让下层模块知道自己的存在,然后在下层模块在变化的时候通知上层模块。
Observer模式的另一个比较有趣的别名是Hollywood模式,因为这个模式可以被描述为“Don't call me, I'll call you.”。
由于Observer如此的常用,所以在实际的使用过程中,这已经是一个烂熟于心的模式。《ASD》一书在讲述这个模式的时候,也没有多少新意,但是还让我有一些点滴的感想:

- Observer模式是典型的由DIP原则驱动的模式。无论是上层数据的变化还是界面的显示都是具体类。具体类应该是不稳定的,不能被依靠。所以必须抽象出接口,就是下层的Subject接口和上层的Observer接口。Subject接口依赖Observer接口。

- 根据单一职责原则(SRP)和接口分离原则(ISP),Subject应该只是处理register和notify的任务,而和具体逻辑无关。这在使用拉模式时尤其需要注意。

- Observer模式有推模式和拉模式两种方法。推模式中,由Subject把数据直接告诉Observer。在拉模式种,Subject只是告诉Observer有事情在变化,然后由Observer来查询是什么数据变化了。究竟使用何种模式应该视具体应用而定。然而常常是两个模式的混合运用。

- 在使用拉模式的时候,Observer要向下层询问获取数据。然而数据属于具体的业务逻辑,和Observer模式的框架无关。因此这个接口不应该被包含在Subject接口中,而需要设立一个单独的业务接口。也就是说,在这种情况下,下层模块要继承两个接口,Subject接口和自己的业务逻辑相关的接口。(如果不这么作,将会形成依赖环)

- 如果把推模式和拉模式混合使用,即是,Subject告诉Observer一个消息,提示是何种变化。Observer判断是否要查询更具体的数据,或者如何查询。这就是消息驱动系统了。

- 另外一种变化是,Observer在注册的时候,就表明自己对何种消息感兴趣。Subject在事件发生的时候,只是通知感兴趣的Observer。

没有评论: