zoukankan      html  css  js  c++  java
  • 观察者模式,即发布-订阅模式

    解释:  

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

    结构图:

      

      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()了。

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

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

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

        

      

      

        

  • 相关阅读:
    Ubuntu16.04下同时安装Anaconda2与Anaconda3
    ansible 常用模块
    docker 笔记 (7) 限制容器
    linux 磁盘
    docker 笔记 (6)搭建本地registry
    docker 笔记 (5)常用命令
    docker 笔记(4) Dockerfile 常用的指令
    NGINX下配置CACHE-CONTROL
    mysql二进制安装
    [Selenium] Explicit wait 方法
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/5581237.html
Copyright © 2011-2022 走看看