美文网首页架构算法设计模式和编程理论程序员
如何让孩子爱上设计模式 ——15.观察者模式(Observer

如何让孩子爱上设计模式 ——15.观察者模式(Observer

作者: coder_pig | 来源:发表于2017-03-07 14:16 被阅读207次

    标签: 设计模式初涉


    描述性文字

    本节讲述的是:观察者模式(Observer Pattern),如果你用过RxJava,相信你对
    这个模式应该不会陌生,当然,RxJava是扩展的观察者模式,这里不做了解,只
    讲解最简单的观察者模式,首先是使用场景,举个最简单的例子,你放学到家,
    很饿,这个时候你妈在厨房做饭,因为你和妈妈达成了写完作业才可以玩农药的
    约定,所以你要先写作业,但是你又很饿,你想当饭做好了第一时间能吃到,你
    可以:

    • 每隔一段时间跑去厨房找你妈,问她饭做好没(轮询
    • 跟你妈说一声,"老妈,饭做好了马上叫我"(订阅或注册),你妈答应了你
      的请求,等她做完饭后立马通知你,这样你就不可以一心一意的做作业了,
      等你妈通知你,然后放下手上的作业,去吃饭。

    上面的场景,使用观察者模式,比起反复的检索,显得更加优雅。

    这个模式,有两个主要角色:被观察者观察者,这里的老妈就属于
    被观察者,而你属于观察者,可能你还有个妹妹和弟弟,一起等饭吃,即:
    一个被观察者可以对应多个观察者,你妈做好饭的时候,会把你们都通知一遍。

    主要角色就这两个,当然,按照设计模式的套路,肯定是会抽象的,
    所以有了另外的两个抽象被观察者抽象观察者,四个角色责任如下:

    四个角色

    • Subject抽象被观察者,把所有观察者对象的引用保存到集合中,然后
      提供添加移除和通知观察者对象更新的方法
    • ConcreteSubject被观察者,集合存放观察者,重写增删和通知观察者
      的方法,当发生变化时通知观察者更新。
    • Observer抽象观察者,定义一个更新接口,给被观察者更新的时候调
    • ConcreteObserver具体观察者,继承抽象观察者,实现具体的更新方法

    一条简单的笔试题示例

    先不画UML类图,我们来写个最简单的观察者模式例子,这个题目是上周去随手记
    笔试的题目,大概题目是这样的:

    花有两种状态,开和关,对于这两种状态,蜜蜂有两种行为,花开的时候采蜜,
    花关的时候回巢这样,然后自己设计类结构,花与蜜蜂解耦,要用到一种设计模式
    实现,输出如下结果,并画出UML类图。

    花开
    蜜蜂1采蜜
    蜜蜂2采蜜
    蜜蜂3采蜜

    花闭
    蜜蜂1回巢
    蜜蜂2回巢
    蜜蜂3回巢

    题目内容大概是这个样子,看完地图第一个想到的设计模式就是观察者模式,
    套路:把花假定为被观察者,蜜蜂为观察者,蜜蜂对花进行订阅,当花的
    状态改变的时候通知蜜蜂做对应操作。
    (因为当时刚从珠海过来,而且浪了一周,基本是裸面,知道这个东西,但是
    写不出代码,2333,贼尴尬,后来通过接口回调的方式实现了...)

    下面就用观察者模式实现上面的题目,首先定义一个抽象观察者——昆虫类

    然后是具体观察类——蜜蜂类

    接着是抽象被观察者 —— 植物类,注册,移除,通知观察者

    再接着是具体被观察者 —— 花朵类,定义一个集合存储观察者,实现相关方法

    最后是客户端调用

    输出结果:

    好的,用观察者模式实现就这么简单,代码都有了,画UML类图就手到擒来了~

    UML类图


    观察者模式的推与拉

    推方式

    被观察者对象向观察者推送主题的详细信息,不管观察者是否需要
    推送的信息通常是被观察者对象的全部或部分数据

    拉方式

    被观察者对象再通知观察者时,只传递少量信息。如果观察者需要更
    详细的信息,可以主动到被观察者中获取,相当于观察者从被观察者
    中拉取数据。一般的套路是:把主题对象自身通过update()方法传递
    给观察者,然后观察者在需要获取的时候,通过这个引用来获取。

    拉方式代码示例

    微信订阅了某个公众号,当有更新的时候会推送提醒,收到提醒后,
    我们需要进入公众号然后点击对应信息查看详细内容。

    抽象观察者用户具体观察者安卓开发者

    抽象被观察者公众号具体被观察者CoderPig公众号

    客户端调用

    输出结果

    好的,拉的模式就那么简单,就是通知观察者更新的时候,把对应引用
    也传过去,然后观察者要什么查什么而已。


    Java中对观察者模式的支持

    在java.util包里面有一个类Observable,它实现了大部分我们需要的目标的功能;
    还有一个接口Observer,它里面定义了update的方法,就是观察者的接口。
    这个就更加简单了:
    口诀:被观察者实现继承Observable,观察者实现Observer接口
    然后有个很关键的地方:当通知变化的时候,需要调用setChange()方法!!!!

    改写下上面的例子,代码如下:

    输出结果

    好的,同样很简单,就是不用自己另外去写抽象观察者或被观察者类,直接
    继承就能玩了,另外有一点要注意的是:Java内置的观察者模式通知多个观察
    者的顺序不是固定的,如果对通知顺序有所依赖的话,还是得自己实现观察者
    模式!


    概念相关拾遗

    关于观察者模式的使用基本就上面这三点,接着说下定义,使用场景,优缺点

    定义

    定义对象见的一种一对多的依赖关系,当一个对象的状态发生改变时,
    所有依赖于它的对象都得到通知并且自动更新。

    使用场景

    • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立
      的对象中使它们可以各自独立地改变和复用。
    • 一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将
      发生改变,也不知道这些对象是谁。
    • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,
      可以使用观察者模式创建一种链式触发机制。

    优缺点

    优点

    • 实现了观察者和目标之间的抽象耦合
    • 实现了动态联动(一个操作会引起其它相关的操作)
    • 支持广播通信

    缺点

    • 互为观察者与被观察者间有循环依赖的话,要注意相互通知引起的死循环!
    • 可能会引起武威操作,误更新。

    本节代码

    https://github.com/coder-pig/DesignPatternsExample/tree/master/14.%20Observer%20Pattern

    相关文章

      网友评论

        本文标题:如何让孩子爱上设计模式 ——15.观察者模式(Observer

        本文链接:https://www.haomeiwen.com/subject/xpsmgttx.html