作者:折纸
集体博客:https://www.zhezhi.press
记录菜鸡的成长之旅!
1. 模式定义和特点
观察者(Observer)模式的定义:指多个对象间 存在一对多的依赖关系 ,当一个对象的状态产生扭转时,所有依赖于它的对象都失去告诉并被自动更新。这种模式有时又称作 公布 - 订阅模式、模型 - 视图模式,它是对象行为型模式。
观察者模式是一种对象行为型模式,其次要长处如下。
- 升高了指标与观察者之间的耦合关系,两者之间是形象耦合关系。合乎依赖倒置准则。
- 指标与观察者之间建设了一套触发机制。
它的次要毛病如下。
- 指标与观察者之间的依赖关系并没有齐全解除,而且有可能呈现循环援用。
- 当观察者对象很多时,告诉的发布会破费很多工夫,影响程序的效率。
2. 模式的类图构造
观察者须要获取到某些数据,但只有主题对象才是真正治理这些数据的角色;这比起所有观察者对立管制同一份数据具备更低的耦合性
咱们常说的 高内聚,低耦合 是什么意思?我的了解:该紧密联系的时候就紧密联系,不该紧密联系的时候就该拆分进去。(同一模块内性能没有必要拆分)
松耦合
当两个对象松耦合时它们仍然能够交互,但不理解彼此的细节 ( 对象之间的相互依赖降到了最低) –> 实现了有弹性的零碎
对于观察者的所有,主题只晓得观察者实现了某个接口(也就是 Observer 接口)。主题不须要晓得观察者的具体类是谁、做了些什么或其余任何细节。
任何时候咱们都能够减少新的观察者。因为主题惟一依赖的货色是一个实现 Observer 接口的对象列表,所以咱们能够随时减少观察者。事实上,在运行时咱们能够用新的观察者取代现有的观察者,主题不会受到任何影响。同样的,也能够在任何时候删除某些观察者。
有新类型的观察者呈现时,主题的代码不须要批改。咱们能够独立地复用主题或观察者。如果咱们在其余中央须要应用主题或观察者,能够轻易地复用。因为二者并非紧耦合。
扭转主题或观察者其中一方,并不会影响另一方。因为两者是松耦合的,所以只有他们之间的接口仍被恪守,咱们就能够自在地扭转他们。
设计准则:为了交互对象之间的松耦合设计而致力
3. 模式的实现
3.1 Java 内置观察者模式类图
3.1.1 如何把对象变成观察者…
如同以前一样,实现观察者接口(java.uitl.Observer),而后调用任何 Observable 对象的 addObserver)办法。不想再当观察者时,调用 deleteObserver()办法就能够了。
3.1.2 可观察者 / 主题要如何送出告诉……
首先,你须要利用扩大 java.util.Observable 接口产生“可观察者”类,而后,需个步骤:
①先调用 setChanged()办法,标记状态曾经扭转的事实。
②而后调用两种 notifyObservers0 办法中的一个:
notifyobservers()或 notifyobservers(object arg)
3.1.3 观察者如何接管告诉……
同以前一样,观察者实现了更新的办法,然而办法的签名不太一样:
如果你想“推”(push)数据给观察者,你能够把数据当作数据对象传送给 notifyObservers(arg)办法。否则,观察者就必须从可观察者对象中“拉”(pull)数据。
其中 setChanged()办法是用来标记状态是否扭转的,好让 notifyObservers()晓得当它被调用时应该更新观察者。如果调用 notifyObservers)之前没有先调用 setChanged(),观察者就“不会”被告诉。让咱们看看 Observable 外部,以理解这所有:
3.2 自定义实现
3.2.1 java.util.Observable 的弊病
java.uitl.Observable 实现了它的 notifyObservers()办法,这导致了告诉观察者的秩序不同于咱们先前的秩序。谁也没有错,只是单方抉择不同的形式实现罢了。然而能够确定的是,如果咱们的代码依赖这样的秩序,就是错的。为什么呢?因为一旦观察者 / 可观察者的实现有所扭转,告诉秩序就会扭转,很可能就会产生谬误的后果。这相对不是咱们所认为的松耦合。
首先,因为 Observable 是一个“类”,你必须设计一个类继承它。如果某类想同时具备 Observable 类和另一个超类的行为,就会陷入两难,毕竟 Java 不反对多重继承。
这限度了 Observable 的复用后劲(而减少复用后劲不正是咱们应用模式最原始的动机吗?)。
再者,因为没有 Observable 接口,所以你无奈建设本人的实现,和 Java 内置的 Observer API 搭配应用,也无奈将 java.util 的实现换成另一套做法的实现(比方说,Observable 将要害的办法爱护起来如果你看看 ObservableAP1,你会发现 setChanged)办法被爱护起来了(被定义成 protected)。那又怎么样呢?这意味着:除非你继承自 Observable,否则你无奈创立 Observable 实例并组合到你本人的对象中来。这个设计违反了第二个设计准则:“多用组合,少用继承”。
如果你可能扩大 java.util.Observable,那么 Observable“可能”能够合乎你的需要。否则,你可能须要像本章结尾的做法那样本人实现这一整套观察者模式。
4. 模式的利用场景
在软件系统中,当零碎一方行为依赖另一方行为的变动时,可应用观察者模式松耦合联动单方,使得一方的变动能够告诉到感兴趣的另一方对象,从而让另一方对象对此做出响应。
通过后面的剖析与利用实例可知观察者模式适宜以下几种情景。
1、对象间存在一对多关系,一个对象的状态产生扭转会影响其余对象。
2、当一个形象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们能够各自独立地扭转和复用。
3、实现相似播送机制的性能,不须要晓得具体收听者,只需散发播送,零碎中感兴趣的对象会主动接管该播送。
4、多层级嵌套应用,造成一种链式触发机制,使得事件具备跨域(逾越两种观察者类型)告诉。
5. 总结
设计准则:
- 封装变动
- 多用组合 少用继承
- 针对接口编程 而不是针对实现编程
- 为交互对象之间的松耦合而致力