简介
为什么要使用观察者模式
在软件系统中,对象和对象之间可能存在着这样的一对多的关系:当一个对象发生改变,它的相关对象也都会随之发生改变。观察者模式描述这样的一种关联关系。
观察者模式应用非常广泛,是使用频率最高的设计模式之一,我们应该着重学习这个设计模式。
什么是观察者模式
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
别名
- 发布-订阅(Publish/Subscribe)模式
- 模型-视图(Model/View)模式
- 源-监听器(Source/Listener)模式
- 依赖(Dependents)模式
类型
对象行为型模式
遵守的原则
迪米特法则、开闭原则
使用频率
★★★★★
角色
角色
- Subject:抽象目标类
- 抽象类
- 具体目标类的父类。
- 被观察的对象。
- 定义了一个观察者集合,并提供方法来增加和删除观察者。
- 定义了通知方法。
- ConcreteSubject:具体目标类
- 具体类
- 继承了抽象目标类。
- 包含经常发生改变的数据。
- 目标类在某些情况下可以省略。
- Observer:抽象观察者
- 接口
- 对观察目标的改变做出相应。
- 声明了更新的方法。
- ConcreteObserver:具体观察者
- 具体类
- 实现了抽象观察者。
- 维护了一个目标对象ConcreteSubject的引用。
- 实现了抽象观察者的更新方法。
- 可以将自己添加到目标类的观察者集合中或将自己从其中删除。
UML类图
代码实现
- 新建抽象目标类Subject.java
- 新建具体目标类ConcreteSubject.java
- 新建抽象观察者Observer.java
- 新建具体观察者ConcreteObserver.java
- 新建测试类Client.java
抽象目标类
Subject.java
abstract class Subject {
// 定义一个观察者集合用于存储所有观察者对象
protected ArrayList<Observer> observers = new ArrayList<Observer>();
// 观察者状态
int subjectState;
public int getSubjectState() {
return subjectState;
}
public void setSubjectState(int subjectState) {
this.subjectState = subjectState;
}
// 注册方法,用于向观察者集合中增加一个观察者
public void attach(Observer observer) {
observers.add(observer);
}
// 注销方法,用于在观察者集合中删除一个观察者
public void detach(Observer observer) {
observers.remove(observer);
}
// 声明抽象通知方法
public abstract void notifyObserver();
}
具体目标类
ConcreteSubject.java
class ConcreteSubject extends Subject {
// 实现通知方法
@Override
public void notifyObserver() {
// 遍历观察者集合,调用每一个观察者的响应方法
for (Object obs : observers) {
((Observer) obs).update(this);
}
}
}
抽象观察者
Observer.java
interface Observer {
// 声明响应方法
public void update(Subject sub);
}
具体观察者
ConcreteObserver.java
class ConcreteObserver implements Observer {
// 观察者名称
String name;
// 观察者状态
int obeserverState;
// 实现响应方法
public ConcreteObserver(String name) {
super();
this.name = name;
}
@Override
public void update(Subject sub) {
obeserverState = sub.getSubjectState();
System.out.println("update oberserver[" + name + "] state:" + obeserverState);
}
}
测试类
Client.java
public class Client {
public static void main(String[] args) {
Subject subject = new ConcreteSubject();
Observer objA = new ConcreteObserver("A");
Observer objB = new ConcreteObserver("B");
subject.attach(objA);
subject.attach(objB);
subject.setSubjectState(1);
subject.notifyObserver();
subject.detach(objB);
subject.setSubjectState(2);
subject.notifyObserver();
}
}
测试
运行Client.java的main()
update oberserver[A] state:1
update oberserver[B] state:1
update oberserver[A] state:2
优缺点
优点
- 遵守“开闭原则”。新增新的观察者和观察目标不需要修改系统原有代码。
- 遵守“迪米特法则”。观察者和目标是抽象耦合的。目标只是维持了一个观察者的集合,而不知道任何一个观察者是属于哪个具体的类的。这样目标和观察者之间的耦合是最小的。
- 支持广播通信。目标发送的通知不需要指定它的接受者。
缺点
待补充
适用环境
当一个对象发生改变,它的相关对象也都会随之发生改变,而不知道它的关联对象有多少个。
使用场景
待补充
扩展
目标和观察者之间可以存在中介者。
问题
Java中,JDK对观察者模式的实现有哪些类,请说明?
待补充。
观察者模式与MVC有什么关系?
待补充。
在软件开发中,你在哪里用到了观察者模式?
待补充。