目录
观察者模式
在软件系统中对象并不是孤立存在的,一个对象行为的改变可能会导致一个或多个其他与之存在依赖关系的对象行为发生改变.观察者模式用于描述对象之间的依赖关系,为实现多个对象之间的联动提供了一种解决方案,它是一种使用频率非常高的设计模式.
观察者模式概述
观察者模式:定义对象之间的一种一对多的依赖关系,使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并被自动更新.
观察者模式的别名有发布-订阅模式,模型-视图模式,源-监听器模式,从属者模式.观察者模式是一种对象行为型模式.
观察者模式结构
观察者模式包含4个角色:
- 目标
- 具体目标
- 观察者
- 具体观察者
观察者模式实现
抽象目标类
import java.util.*;
abstract class Subject {
//定义一个观察者集合用于存储所有观察者对象
protected ArrayList observers<Observer> = new ArrayList();
//注册方法,用于向观察者集合中增加一个观察者
public void attach(Observer observer) {
observers.add(observer);
}
//注销方法,用于在观察者集合中删除一个观察者
public void detach(Observer observer) {
observers.remove(observer);
}
//声明抽象通知方法
public abstract void notify();
}
具体目标类
class ConcreteSubject extends Subject {
//实现通知方法
public void notify() {
//遍历观察者集合,调用每一个观察者的响应方法
for(Object obs:observers) {
((Observer)obs).update();
}
}
}
抽象观察者
interface Observer {
//声明响应方法
public void update();
}
具体观察者
class ConcreteObserver implements Observer {
//实现响应方法
public void update() {
//具体响应代码
}
}
在有些更加复杂的情况下,具体观察者类ConcreteObserver的update()方法在执行时需要使用到具体目标类ConcreteSubject中的状态(属性),因此在ConcreteObserver与ConcreteSubject之间有时候还存在关联或依赖关系.
如果ConcreteObserver的update()方法不需要使用到ConcreteSubject中的状态属性,则可以对观察者模式的标准结构进行简化,在具体观察者ConcreteObserver和具体目标ConcreteSubject之间无须维持对象引用.如果在具体层具有关联关系,系统的扩展性将受到一定的影响,增加新的具体目标类有时候需要修改原有观察者的代码,在一定程度上违反了“开闭原则”,但是如果原有观察者类无须关联新增的具体目标,则系统扩展性不受影响.
JDK对观察者模式的支持
观察者模式在Java语言中占据非常重要的地位.在JDK的java.util包中提供了Observable类以及Observer接口,它们构成了JDK对观察者模式的支持.
java.util.Observer接口充当抽象观察者.
java.util.Observable类充当观察目标类
用户可以直接使用Observer接口和Observable类来作为观察者模式的抽象层,再自定义具体观察者类和具体观察目标类,通过使用JDK中的Observer接口和Observable类,可以更加方便地在Java语言中应用观察者模式.
观察者模式与Java事件处理
观察者模式与MVC
观察者模式优/缺点与适用环境
观察者模式优点
- 可以实现表示层和数据逻辑层的分离.
- 在观察目标和观察者之间建立一个抽象的耦合.
- 支持广播通信且符合开闭原则.
观察者模式缺点
- 将所有的观察者都通知到会花费很多时间.
- 如果存在循环调用可能导致系统崩溃.
- 没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅知道观察目标发生了变化.
观察者模式适用环境
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用.
- 一个对象的改变导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁.
- 需要在系统中创建一个触发链.