先看其意图,GOF说:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都能得到通知并被自动更新。从最原始最本能的思维出发,上述意图看起来似乎是如下一种情况


 
     从上图看起来,貌似挺复杂的,当Subject的State变化时调用StateChanged(),那在StateChanged()中调用Class1、Class2、Class3的相应的方法。要调用一个类的方法,就一定持有这个类的引用,无论你用何种方式得到这个引用。在Class1的DoSthWhileStateChanged1()方法中,或许还需要获取Subject的相应数据,似乎更加麻烦了,而且也更常见。
     且先不管许多大做上介绍的如何从这种困境中一步一步跳出来,最终得到一个赏心悦目的Observer模式,先看看我们到底要做的是个什么事情。看图,在Subject的State变化时,我们让其他3个类的对象做了相应的动作,在这里,3个和1个有什么区别呢?统一来看,反正就是让其他的对象也随着状态的变化更新。还是说的太复杂,再白一点,无非是在一个类中调用了其他类的方法,或许还传递了参数。
      我们做的就是这么简单的一件事,可是为什么觉得复杂了呢?先按下不表,扯点别的。说说设计模式的由来,ChristoPher Alexander说:“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。当然这是建筑上的,GOF把这个概念搬到了软件中。既然模式是问题及其解决方案,那先要看看问题是什么。软件中最大的问题也许就是变化了。GOF说:“获得最大限度复用的关键在于对新需求和已知需求发生变化时的预见性,要求你的系统设计要能相应的改进。”看来,软件中的设计模式,绝大部分在于变化和解决变化的方案。
 扯远了再扯回来,这里本质很简单的一件事情,我们觉得复杂了,为什么?答案是变化。调用一个类的方法到调用三个类的方法,有变化:类不同了,多个了,调用方法的签名不同了,每个都不一样,更有可能,不是3个,是4个,或者根本不知道是几个了。情况一下子变得复杂起来。
      既然一切罪行都由变化引起,那么解决变化刻不容缓。先想一想我们能对变化做什么?能让其不变最好,否则也要尽量让其少变小变,时间上,不要让其一开始就变来变去,位置上,把变化集中起来管理,再不行的话,就做你该做的吧。这里,我们先看看能消灭什么?扯点别的先,都上过小学,都大扫除过,老师安排说1组干什么,2组干什么,他并不管你1组都有谁谁谁,2组都有谁谁谁。发现了吧,一个1组代表了好几号人,因为他们都干相同性质的事情。具体谁谁谁对老师来说没啥不一样,他也不关心。可见,统一签名,是不用关注变化的一个有效手段。在这里,不管DoSthWhileStateChanged1()也好DoSthWhileStateChanged2()也好,都是State变了后要做的事,不妨统一命名成DoSthWhileStateChanged(),这完全没有什么问题。有些变化可以统一,有些则没法消除,比如说不同的类:Class1,Class2和Class3,就是3个不同的类,你无可奈何,因此你的Subject迟早要与这3个类遭遇。那么如何削弱这种依赖关系?依赖的越晚,这种依赖关系越弱,其实也就是晚绑。要让这3个做了一件相同性质的事情获得晚绑的权利,怎么办?给其一个接口最合适不过了。这样,Subject就不用一开始就依赖这3个具体类了。如图
 
 
      再继续看,既然Subject要调用实现了IDoSomething接口的一系列类的DoSthWhileStateChanged()方法,势必要有一个保存这些类的引用的列表,对于一个集合操作,势必要有Add、Remove等集合操作方法。看出来了,在这么一种应用场景下,总有这种逻辑存在,提取出来看看行不行?顺便整理一下,IDoSomething就叫IObserver吧,3个Class类就用一个Observer类表示吧,DoSthWhileStateChanged()不如叫Update()来得更简洁明了。对集合操作的Add呢,不妨叫Register更符合语意,那StateChanged()本来就是让Observer对象做动作,不妨叫Notify()吧,如果Observer中需要Subject的数据,那也需要Subject的一个引用。看看图:
 
 

     呵,看起来像是传统的Observer模式了吧。其实管他什么模式呢,重点是达到了我们的目的。我们用继承达到了晚绑的目的,用统一签名的方法,消除了调用时的变化。调用其他类的方法,本来这件很简单的事情,现在看来也变得简单了,无论你调用哪个类的方法,让这个类实现IObserver接口(统一方法签名,同时给类型晚绑提供了条件),注册到Subject中就可以了。
      从这个层面上看,Vistor模式和Observer模式有异曲同工之处。只不过Ovserver模式是一个类中调用其他一系列类中的方法,而vistor模式恰相反,是一系列类调用一个类中的不同方法,不过利用了多态,让每个类都能自动调用到这个类中相应的方法。不管什么模式,只要把握住了问题在代码上的本质体现,掌握了解决问题的指导思想和方式方法,到最后是什么模式,已经无关重要了,重要的是它解决了问题。其实呢,我们知道委托就是晚绑了一个方法的调用,那不正是我们Observer模式需要的么?那么显然用委托可以方便的实现Observer模式。基于委托的事件呢,在我看来就是个Observer模式,或许根本就不需要说是什么Observer模式。
      说了这么多Observer模式,其实我本意不在此,我仅仅是想说,模式只是种结果,正确的目标、指导思想、方式方法才是我们更应关注的东西。(待续)

posted on 2008-07-19 19:05  绿蚂蚁  阅读(527)  评论(1编辑  收藏  举报