观察者模式,即发布-订阅模式

解释:  

  定义了一种一对多的依赖关系,让多个观察者对象同事监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。

结构图:

  

  Subject类,主题通知者、抽象通知者。一般用一个抽象类或者一个接口实现。将所有对观察者对象的引用保存在一个聚集里,每一个主题都可以有任何数量的观察者。

  

  Observer类,抽象观察者、更新接口。一般用一个抽象类或者一个接口实现。为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。

  

  ConcreteSubject类,具体主题、具体通知者。通常用一个具体子类实现。将有关状态存入具体观察者对象。在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

  

  

  ConcreteObserver类,具体观察者。通常用一个具体子类实现。实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。可以保存一个指向具体主题对象的引用。

  

  客户端代码:

  

  

针对的问题:

  将一个系统分隔成一系列相互协作的类有一个很不好的副作用。那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合。这样会给维护、扩展、重用都带来不便。

优点:

  观察者模式的关键对象:Subject和Observer。

  一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了变化,所有Observer都可以得到通知。

  Subject发出通知时,并不需要知道谁是它的观察者(即,具体的观察者是谁?)

  任何一个具体观察者不知道,不需要知道其他观察者的存在。

  解除耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。依赖倒转原则的最佳体现。

使用环境:

  当一个对象的改变需要同时改变其他对象的时候。且不知道具体有多少个对象有待改变。

  当一个抽象模型有两个方面,其中一方面依赖于另一方面。观察者模式可以将这两者封装在独立的对象中,使他们各自独立地改变和复用。

使用建议:

  什么时候使用抽象类?什么时候使用接口?

  当具体观察者很相似,使用抽象类。这样可以共用一些代码。用接口只是方法上的实现,没什么太大的意义。

  当具体观察者是风马牛不相及的类,但它们都需要根据统治者的通知来做出Update()的操作,那使用接口就可以实现。

缺点:

  尽管用了依赖倒转原则,但是“抽象通知者”还是依赖“抽象观察者”,即没有了抽象观察者,通知的功能格式完不成的。

  每个具体的观察者,”更新“的方法不一定同名。

优化:

  使用事件委托。去掉父类“抽象观察者”,将”更新“方法名改为各自适合的方法名。

  去除“抽象通知者”对“抽象观察者”的依赖。将抽象通知类的“增加”、“减少”以及“通知”时遍历抽象观察者都去除。转而让客户端使用委托来实现。解决耦合问题。

  具体观察类,更新方法名不同。

   

  抽象通知者,不依赖抽象观察,“增加”、“减少”、“通知”时遍历抽象观察者都没必要了。

  

  

    声明一个委托

  

  具体通知类,使用委托,实现不同方法名的“更新”。

  

  客户端:实现不同方法名的“更新”,实现抽象通知类与抽象观察类的解绑,不用“增加”、“减少”,使用委托即可(一个委托可以搭载多个方法,所有方法被依次唤起)。

  

  对比优化前:耦合更加严重些。

  

委托和事件:

  就是一种引用方法的类型。一旦为委托分配了方法,委托将于该方法具有完全相同的行为。

  委托方法的使用可以像其他任何方法一样,具有参数和返回值。

  委托可以看做是对函数的抽象。是函数的‘类’,委托实例代表了一个具体的函数。delegate void EventHandler(),理解为声明了一个特殊的类;public event EventHandler Update(),理解为声明了一个时间委托方法叫“更新”;new EventHandler(tongshi1.CloseStockMarket),理解为一个委托的实例,将tongshi1.CloseStockMarket()委托给huhansan.Update()了。

  一个委托可以搭载多个方法,所有方法被依次唤起。

  更重要的是,委托对象所搭载的方法并不需要属于同一个类。

  前提:对托所搭载的所有方法必须具有相同的原型和形式(即,拥有相同的参数列表和返回值类型)。

 

    

  

  

    

 

posted @ 2016-06-13 16:57  PanPan003  阅读(559)  评论(0编辑  收藏  举报