设计模式(java)

观察者模式

2019-01-15  本文已影响0人  greensure

参考资料:

https://www.imooc.com/learn/415

https://blog.csdn.net/itachi85/article/details/50773358

观察者模式模式实践代码

目录

1、什么是观察者模式

2、观察者模式的2种实现方式

3、观察者模式的2种实现方式的比较

4、观察者模式的的角色

5、观察者模式的优缺点

6、观察者模式的应用场景

7、观察者模式的衍生

8、观察者模式的结构

9、观察者模式的通用代码

10、观察者模式的本质

11、从六大方面观察者模式

12、利用JAVA提供的观察者实现

1、什么是观察者模式

定义:

观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

其他定义参考:

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

注:一对一属于一对多;

一个目标可以有任意多个观察者对象,一但目标的状态发生了改变,所有注册的观察者都会得到通知,各个观察者会对通知做出相应的响应,执行相应的业务逻辑处理;

2、观察者模式的2种实现方式

(1)推模型

目标对象主动向观察者推送目标的详细信息,推送的信息通常是目标对象的全部或部分数据;

注:不管观察者是否需要 ,推送的信息通常是目标对象的全部或部分数据;

(2)拉模型

目标对象在通知观察者的时候,只传递少量信息。

如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。

一般这种模型的实现中,会把目标对象自身通过update方法传递给观察者。

3、观察者模式的2种实现方式的比较

4、观察者模式的的角色

5、观察者模式的优缺点

优点:

第一、观察者模式实现了观察者和目标之间的抽象耦合

解释:原本目标对象在状态发生改变的时候,需要直接调用所有观察者对象,但是抽象出观察者接口以后,目标和观察者就只是在抽象层面上耦合,也就是说目标只是知道观察者的接口,并不知道具体的观察者的类,从而实现了目标类和具体的观察者之间的

第二、观察者模式实现了动态联动

解释:所谓联动,就是做一个操作,会引起其他相关的操作,由于观察者模式对注册实行管理,那就可以在运行期间通过动态的控制,注册的观察者来控制 某个动作的联动范围,从而实现动态联动。

第三、观察者模式支持广播通信

解释:由于目标发送通知给观察者,是面向所有注册的观察者,所以每次目标通知的信息就要对所有注册的观察者进行保护,当然也可以在目标上添加新的功能来限制广播的范围

缺点:

可能会引起无谓的操作;

解释:

由于观察者每次都是广播通信,不管观察者是不是需要,每个观察者都会被调用update方法,若观察者不需要执行相应的处理,那么这些操作是不是就浪费了,其实浪费是新的问题,最怕引起误会,就麻烦了。

其实模式的应用,就像孙子兵法的36计,具体用在什么样的战场上,就要看用计的人能不能熟练应用。

在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

6、观察者模式的应用场景

建议在以下情况中选用观察者模式:

第一 当一个抽象模型有2个方面,其中一个方面的操作依赖于另一个方面的状态变化;

解释:将这2者封装成观察者和目标对象,当目标对象变化的时候,依赖于它的观察者对象也会发生相应的变化,这样就可以把抽象模型的这两个方面分离开,使得他们可以独立的改变、复用

第二 如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变

注: 这种情况,被更改的对象很明显是目标对象,而需要连带修改的其他对象就可以当作是多个观察者对象

第三 当一个对象必须通知其他的对象,但你又希望这个对象和其他被它通知的对象是松散耦合的;

注:这个对象不想知道具体被通知的对象,这种情况可以选用观察者模式,这个对象就相当于是目标对象,而被他通知的对象就是观察者对象;

7、观察者模式的衍生

TODO

8、观察者模式的结构

9、观察者模式的通用代码

步骤:

1)、是目标对象的定义

2)、是具体的目标对象的定义

3)、再来看看观察者的接口定义

4)、看看观察者的具体实现

10、观察者模式的本质

当修改目标对象的状态的时候,就会触发相应的通知,然后会循环调用所有注册观察者对象相应的方法,其实就相当于联动调用这些观察者的方法

理解观察者模式的本质很重要,对我们识别和使用观察者模式具有重要的意义,尤其是在练习使用的时候万变不离其宗

11、从六大方面观察者模式

(1)目标与观察者之间的关系

按照模式的定义,目标与观察者之间是联系的,是一对多的关系;

一个观察者可以对多个目标;

如果观察者为多个目标定义了通知,更新的方法都是update方法的话,这样会带来麻烦需要接收多个目标的通知,若是一个update方法,需要在方法内部区分。一般情况下观察者应该为不同的观察者目标立不同的观察方法;

(2)单向依赖

在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖目标,而不是目标依赖观察者,他们之间的联系,主动权掌握在目标者的手中,只有目标知道什么时候需要通知观察者,在整个过程中观察者是被动的,被动的等待目标的通知,等待目标传值给他;

(3)命名建议

1)目标接口的定义,建议在名称后面跟Subject;

2)观察者接口的定义,建议在名称后面跟Observer;

3)观察者接口的更新方法,建议名称为update

(4)触发通知的时机

在实现观察者模式的时候,一定要注意触发通知的时机,一般情况下是在完成状态维护之后触发,因为通知会传递数据,不能先通知后改变数据,这很容易出问题,会导致观察者目标和对象状态不一致;

(5)观察者模式的调用顺序

TODO

(6)通知的顺序

从理论上来说,当目标对象的状态变化后,通知所有的观察者的时候,需求是不确定的,因此观察者实现的功能绝对不能依赖于通知的顺序,也就是说,多个观察者之间的顺序是平行的,相互不应该有先后依赖的关系

12、利用JAVA提供的观察者实现

JAVA实现与自己实现的对比(四点):

(1)不需要再定义观察者和目标的接口了,JDK帮忙定义了;

(2)具体的目标实现里面不需要再维护观察者的注册信息了,这个在java中的Observable类里面已经帮忙实现好了;

(3)触发通知的方式有一点变化,要先调用setChanged方法,这个是JAVA为了帮助实现更精确的触发控制而提供的功能;

(4)具体观察者的实现里面,update方法其实能同时支持推模型和拉模型,这个是JAVA在定义的时候,就已经考虑进去了;

上一篇 下一篇

猜你喜欢

热点阅读