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

标签: 设计模式初涉

描述性文字

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

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

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

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

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

四个角色

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

一条简单的笔试题示例

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最后是客户端调用

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

输出结果:

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

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

UML类图

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

观察者模式的推与拉

推方式

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

拉方式

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

拉方式代码示例

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

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

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

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

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

客户端调用

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

输出结果

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

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

Java中对观察者模式的支持

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

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

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

输出结果

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

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

概念相关拾遗

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

定义

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

使用场景

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

优缺点

优点

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

缺点

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

本节代码

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

    原文作者:架构
    原文地址: https://www.jianshu.com/p/43bac7e8616f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞