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

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

标签: 设计模式初涉


描述性文字

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

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

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

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

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

四个角色

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

一条简单的笔试题示例

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

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

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

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

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

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

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

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第1张图片

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

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第2张图片

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

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第3张图片

最后是客户端调用

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第4张图片

输出结果:

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第5张图片

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

UML类图

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第6张图片


观察者模式的推与拉

推方式

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

拉方式

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

拉方式代码示例

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

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

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

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第7张图片

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第8张图片

客户端调用

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第9张图片

输出结果

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


Java中对观察者模式的支持

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

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

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第10张图片

如何让孩子爱上设计模式 ——15.观察者模式(Observer Pattern)_第11张图片

输出结果

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


概念相关拾遗

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

定义

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

使用场景

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

优缺点

优点

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

缺点

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

本节代码

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

你可能感兴趣的:(设计模式初涉,如何让孩子爱上设计模式)