概述
- 定义 : 定义了对象之间的一对多依赖, 让多个观察者对象同时监听某一个主题对象, 当主题对象发生变化时, 它的所有依赖者(观察者)都会收到通知并更新
- 类型 : 行为型
适用场景
- 关联行为场景, 建立一套触发机制
优点
- 观察者和被观察者之间建立一个抽象的耦合
- 观察者模式支持广播通信
缺点
- 观察者之间有过多的细节依赖, 提高时间消耗及程序复杂度
- 使用要得当, 要避免循环调用
模式角色
-
**Subject(目标) : **
- 目标知道它的观察者。可以有任意多个观察者观察同一个目标。
- 提供注册和删除观察者对象的接口。
-
Observer(观察者): 为那些在目标发生改变时需获得通知的对象定义一个更新接口。
-
ConcreteSubject(具体目标):
- 将有关状态存入各ConcreteObserver对象。
- 当它的状态发生改变时, 向它的各个观察者发出通知。
-
ConcreteObserver(具体观察者):
- 维护一个指向ConcreteSubject对象的引用。
- 存储有关状态,这些状态应与目标的状态保持一致。
- 实现Observer的更新接口以使自身状态与目标的状态保持一致
代码实现
场景
以QQ空间发布动态为场景, 分为几个部分, Qzone空间可以发布动态Dynamic, QQ关注了某个Qzone空间时, 就能接收到Qzone空间发布的动态
- Qzone : 被观察者Subject, 也就是模式中的Subject
- QQ : 观察者
UML类图
代码
- JDK中对于观察者模式有一些支持
- 提供了Observable类表示被观察者
- 提供了Observer表示观察者
详细代码如下 :
动态 :
/**
* 空间动态
*
* @author 七夜雪
* @create 2018-11-24 15:19
*/
public class Dynamic {
private String content;
public Dynamic(String content) {
this.content = content;
}
public String getContent() {
return content;
}
}
目标 :
/**
* QQ空间
* 继承Observable称为被观察者
* @author 七夜雪
* @create 2018-11-24 15:07
*/
public class Qzone extends Observable {
private String name;
public Qzone(String name) {
this.name = name;
}
/**
* 发布一条动态
* @return
*/
public void publishDynamic(String content){
Dynamic dynamic = new Dynamic(content);
setChanged();
notifyObservers(dynamic);
}
public String getName() {
return name;
}
}
观察者 :
import java.util.Observable;
import java.util.Observer;
/**
* @author 七夜雪
* @create 2018-11-24 15:10
*/
public class QQ implements Observer {
@Override
public void update(Observable o, Object arg) {
Qzone qzone = (Qzone) o;
Dynamic dynamic = (Dynamic) arg;
System.out.println(qzone.getName() + " 发布了一条动态 :" + dynamic.getContent());
}
}
测试代码 :
/**
* 测试类
*
* @author 七夜雪
* @create 2018-11-24 15:25
*/
public class Client {
public static void main(String[] args) {
Qzone qzone = new Qzone("七夜雪");
QQ qq = new QQ();
qzone.addObserver(qq);
qzone.publishDynamic("听雪楼中听雪落, 彼岸花开彼岸零");
}
}
测试结果 :
七夜雪 发布了一条动态 :听雪楼中听雪落, 彼岸花开彼岸零
本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>