观察者模式(Observer Pattern)是一个非常受欢迎、使用率非常高的一种设计模式,它分为观察者、被观察者,观察者对观察者的某个变化高度敏感,当被观察者某个状态发生变化时,被观察者提醒观察者,观察者作出响应。比如比较火的框架 RxJava 就是基于观察者模式。当程序具有关联行为时,它将关联双方分为观察者和被观察者,将观察者和被观察者解耦,使得它们之间依赖性更小,还可以实现 UI 层和具体业务逻辑的解耦。

观察者模式主要分为四个部分:抽象被观察者、具体被观察者、抽象观察者、具体被观察者
抽象被观察者:如图中的 Observable,它会把所有的观察者对象的引用保存在一个集合中。
具体被观察者:如图中的 ObservableA、ObservableB,继承自 Observable,会将被观察者的状态保存到观察者对象中,当状态发生变化便提醒观察该被观察的所有观察者。
抽象观察者:如图中的 Observer,它定义了一个接口来响应被观察者发出的状态更新通知。
具体观察者:如图中的 ObserverA、ObserverB,继承自 Observer,实现 Observer 的接口,在被观察者状态发生变化时响应。
下面我们通过一个例子来讲解一下观察者模式的简单实现,有两个裁判员 A,B,裁判员 A 管选手 A 和选手 B,裁判员 B 管选手 C 和 选手 D,当裁判员说出一段词时,选手 A 和选手 C 要念出这段词,选手 B 和选手 D 要唱出这段词:
- 创建抽象观察者 Observer.java:
//抽象观察者,对应例子中所有选手的父类
public interface Observer {
//作出响应
void response(Observer o,String arg);
}- 创建抽象被观察者 Observable.java:
//抽象被观察者,即例子中裁判员的父类
public abstract class Observable {
//所有观察者的对象,即例子中观察裁判员台词的选手
protected List<Observer> observers = new ArrayList<Observer>();
//将观察被观察者的观察者添加到这个被观察者的队伍中
public void addObserver(Observer observer){
observers.add(observer);
}
}- 创建具体被观察者 ObservableA.java,ObservableB.java,即裁判员 A,B(本例子总裁判员 A 和 B 状态变化相同,所有只对裁判员 A 的代码进行注释,实际开发过程中,可以使用不同的状态变化):
//具体被观察者 A,即裁判员 A
public class ObservableA extends Observable {
//被观察者的状态,类型不限于 String,这里对应裁判员的台词
private String content;
//被观察者状态发生变化,即裁判员说出台词
public void setFlag(String content) {
this.content = content;
//提醒观察者,即所有选手选手
notifyAllObservers();
}
//提醒所有观察者的方法
public void notifyAllObservers(){
for (Observer observer:
observers) {
//核心就是调用所有所有观察这个被观察者的观察者的响应事件
observer.response(observer,content);
}
}
}
//具体被观察者 B,及裁判员 B,因为这个例子两个裁判员状态变化都是发出台词,便不做具体注释
public class ObservableB extends Observable {
private String content;
public void setFlag(String content) {
this.content = content;
notifyAllObservers();
}
public void notifyAllObservers(){
for (Observer observer:
observers) {
observer.response(observer,content);
}
}
}- 创建具体观察者 ObserverA.java,ObserverB.java,ObserverC.java,ObserverD.java,即选手 A、B、C、D(A 和 B 观察裁判员 A,C 和 D 观察裁判员 B,选手 A 和 C 需要念出台词,选手 B 和 D 需要唱出台词。因为这个例子中作出的响应事件大致一致,所有只对选手 A 的代码进行注释,实际开发中可以写不同的响应事件),大家要是觉得下面代码太长懒得看,可以只看 ObserverA就行:
//观察者 A,即选手 A
public class ObserverA implements Observer {
//观察者名字
private String name;
//要观察的对象,即被观察者 裁判员
private Observable observable;
public ObserverA(String name,Observable observable){
this.name = name;
this.observable = observable;
//将自己添加到自己想要观察的被观察者的观察者队列中
this.observable.addObserver(this);
}
//响应事件
@Override
public void response(Observer o, String arg) {
System.out.println("我是:"+o+",我要念出这段台词:"+arg);
}
//重新 toString() 方法,传入自己的名字
@Override
public String toString() {
return name;
}
}
//具体观察者 B,即选手B
public class ObserverB implements Observer {
private String name;
private Observable observable;
public ObserverB(String name,Observable observable){
this.name = name;
this.observable = observable;
this.observable.addObserver(this);
}
@Override
public void response(Observer o, String arg) {
System.out.println("我是:"+o+",我要唱出这段台词:"+arg);
}
@Override
public String toString() {
return name;
}
}
//具体观察者 C,即选手 C
public class ObserverC implements Observer {
private String name;
private Observable observable;
public ObserverC(String name, Observable observable){
this.name = name;
this.observable = observable;
this.observable.addObserver(this);
}
@Override
public void response(Observer o, String arg) {
System.out.println("我是:"+o+",我要念出这段台词:"+arg);
}
@Override
public String toString() {
return name;
}
}
//具体观察者 D,即选手 D
public class ObserverD implements Observer {
private String name;
private Observable observable;
public ObserverD(String name, Observable observable){
this.name = name;
this.observable = observable;
this.observable.addObserver(this);
}
@Override
public void response(Observer o, String arg) {
System.out.println("我是:"+o+",我要唱出这段台词:"+arg);
}
@Override
public String toString() {
return name;
}
}- 进行测试:
public class Main {
public static void main(String[] args) {
//两个被观察者,即裁判员 A、B
ObservableA observableA = new ObservableA();
ObservableB observableB = new ObservableB();
//四个观察者,即选手 A、B、C、D
ObserverA a = new ObserverA("选手A",observableA);
ObserverB b = new ObserverB("选手B",observableA);
ObserverC c = new ObserverC("选手C",observableB);
ObserverD d = new ObserverD("选手D",observableB);
//裁判员 A 发出台词
observableA.setFlag("我说今晚夜光那么美");
//裁判员 B 发出台词
observableB.setFlag("你说相思赋予谁");
}
}- 结果:

观察者简单使用就讲完了,那么它有什么优点呢?它把一个关联关系的双方分为观察者和被观察者,对双方代码进行了解耦,使得代码以后维护和修改什么容易,可扩展性也强,在订阅发布中一对一或者一对多的订阅有很好的实现。
- 观察者模式的适用场景
第一种情况是关联场景,但要是可以拆分的关联场景
第二种情况是一对多触发场景
第三种是信息交换场景
2万+

被折叠的 条评论
为什么被折叠?



