0x00 概述
观察者模式定义了一种一对多的依赖关系,观察对象的状态发生改变时,每一个观察者都能够得到通知并做出相应的改变。也称为发布-订阅模式。
0x01 组成结构
- Observable:被观察者,持有一个观察者对象的集合,同时具有添加观察者、移除观察者的方法,以及一个通知所有观察者的方法。
- ConcreteObservable:具体被观察者,包含易改变的状态。
- Observer:观察者接口,提供一个update方法,用于对被观察者的状态发生变化是做出响应。
- ConcreteObserver:具体观察者,一般持有一个被观察者引用。
UML架构图如下:
0x10 实现方式
- 推模式:被观察者向观察者推送具体的所有或者部分状态信息,不论观察者是否需要,该方式不利于扩展。
- 拉模式:被观察者向观察者传递本身对象的引用,观察者通过该引用得到需要的信息。该方式由于传递引用,暴露的东西太多。
0x11 示例代码
jdk提供了Observable(抽象被观察者)和Observer(抽象观察者)两个接口,本文以此基础来讲述。
package com.kkk.pattern.observer;
import java.util.Observable;
import java.util.Random;
/**
* 充当具体被观察者。
* Created by z3jjlzt on 2018/2/10.
*/
public class GamblingHouse extends Observable {
private static final Random random = new Random();
public void publishNum() {
setChanged();
}
public int getLuckyNum() {
return random.nextInt(25);
}
}
/**
* 彩民,充当具体观察者。
* Created by z3jjlzt on 2018/2/10.
*/
public class Punters implements Observer {
private int luckyNum;
public Punters() {
}
public Punters(int luckyNum) {
this.luckyNum = luckyNum;
}
public int getLuckyNum() {
return luckyNum;
}
public void setLuckyNum(int luckyNum) {
this.luckyNum = luckyNum;
}
@Override
public void update(Observable o, Object arg) {
if (((GamblingHouse) o).getLuckyNum() == this.luckyNum) {
System.out.println("恭喜你中奖了 :" + luckyNum);
} else {
System.out.println("未中奖" + ((GamblingHouse) o).getLuckyNum());
}
}
}
/**
* Created by z3jjlzt on 2018/2/10.
*/
public class Client {
public static void main(String[] args) {
Punters p1 = new Punters(8);
Punters p2 = new Punters(24);
GamblingHouse gamblingHouse = new GamblingHouse();
gamblingHouse.addObserver(p1);
gamblingHouse.addObserver(p2);
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
gamblingHouse.publishNum();
gamblingHouse.notifyObservers();
}
}
运行结果:
恭喜你中奖了 :24
未中奖19
未中奖2
未中奖8
未中奖4
未中奖19
未中奖3
未中奖0
未中奖8
未中奖13
未中奖11
未中奖9
未中奖4
未中奖1
0xff 总结
- 优点:提供稳定的消息传递机制,使得数据层与表现层分离。
- 缺点:当观察者过多时,通知时间长。
- 适用场景:一个对象的状态改变需要被其他多个对象所捕获。