设计模式——观察者模式
简介——什么是观察者模式
观察者模式是一种定义对象相互之间依赖关系的一种设计模式,它属于设计模式中的行为模式,通过发布/订阅的方式在对象之间互相传送消息
一般观察者使用步骤
- 订阅事件(addObserver)
- 被观察者发布事件
- 观察者响应事件
举例说明
我们可以用一个例子来解释一下观察者模式,犯罪嫌疑人与警察的例子
角色定义
- 犯罪嫌疑人(被观察者)
- 警察(观察者)
分析
当警察对犯罪嫌疑人进行盯梢的时候,一旦犯罪嫌疑人选择逃跑或其它不利于抓捕的行为时,警察就会做出一系列反应,所以在本案例中,犯罪嫌疑人就是被观察的对象,而警察就是观察者,也叫盯梢者
我们来看一下案例的一个流程图
当然这里订阅事件,不是犯罪嫌疑人(被观察者)自已订阅的,但这不影响我们举例。
在本案例中,观察者的身份可能有多个,比如说警察或军人,因为对于特殊重大案情,可能需要武警部队参加抓捕,比如说我们边境缉毒案件,但他们的目的都是一致的——抓捕嫌疑人,只不过在本案件中,他们所做的具体的事不一样。
手写代码
1. 定义被观察者接口(注册或添加事件、删除事件、通知事件)
public interface Observable {
/**
* 注册/添加观察者
*
* @param observer 观察者
*/
public void addObserver(Observer observer);
/**
* 移动观察者
*
* @param observer 观察者
*/
public void removeObserver(Observer observer);
/**
* 通知所有的观察者
*/
public void notifyObservers();
}
2. 定义观察者统一接口,处理事件
public interface Observer {
/**
* 根据不同的事件,做出不同的反应
*
* @param event event
*/
public void handle(Event event);
}
3. 定义枚举事件类型
public enum Event {
//玩
PLAY(1),
//逃跑
RUN(2);
Integer index;
/**
* 构造
*
* @param index
*/
Event(Integer index) {
this.index = index;
}
public Integer getIndex() {
return this.index;
}
}
4. 定义具体被观察者(X犯罪嫌疑人)
在被观察者里面有一个用于维护订阅了事件的被观察者集合
public class BadMan implements Observable {
// Observer集合
private final List<Observer> observers = new LinkedList<>();
@Override
public void addObserver(Observer observer) {
this.observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
this.observers.remove(observer);
}
@Override
public void notifyObservers(Event event) {
this.observers.forEach(observer -> observer.handle(event));
}
/**
* 逃跑行为
*/
public void runAction() {
System.out.println("犯罪嫌疑人 逃跑");
notifyObservers(Event.RUN);
}
/**
* 玩行为
*/
public void playAction() {
System.out.println("犯罪嫌疑人 玩");
notifyObservers(Event.PLAY);
}
}
5. 定义具体的观察者(警察A 和 警察B)
public class PoliceA implements Observer {
@Override
public void handle(Event event) {
System.out.println("PoliceA:receive event = " + event.name());
if (event == Event.PLAY) {
System.out.println("PoliceA: 他要玩就让他玩吧");
} else if (event == Event.RUN) {
System.out.println("PoliceA: 守住A口");
}
}
}
public class PoliceB implements Observer {
@Override
public void handle(Event event) {
System.out.println("PoliceB:receive event = " + event.name());
if (event == Event.PLAY) {
System.out.println("PoliceB: 他要玩就让他玩吧");
} else if (event == Event.RUN) {
System.out.println("PoliceB: 守住B口");
}
}
}
6. 测试
public static void main(String[] args) {
BadMan badMan = new BadMan();
badMan.addObserver(new PoliceA());
badMan.addObserver(new PoliceB());
badMan.playAction();
badMan.runAction();
}
运行效果
犯罪嫌疑人 玩
PoliceA:receive event = PLAY
PoliceA: 他要玩就让他玩吧
PoliceB:receive event = PLAY
PoliceB: 他要玩就让他玩吧
犯罪嫌疑人 逃跑
PoliceA:receive event = RUN
PoliceA: 守住A口
PoliceB:receive event = RUN
PoliceB: 守住B口
JDK中自带的实现工具
被观察者 java.util.Observable
观察者 java.util.Observer
Observable类源码,里面也是定义了一个Observer集合,有两个重载的notifyObservers方法,与我们代码不同的是,里面有一个changed变量,在notifyObservers方法里面,需要我们手动地将chaned改为true,才能将事件通知给Observer
Observer类源码,里面定义了一个update方法,可以传入事件产生源,和 一个其它参数
1. 定义被具体被观察者,继承Observable
public class BadMan extends Observable {
/**
* 逃跑行为
*/
public void runAction() {
System.out.println("犯罪嫌疑人 逃跑");
setChanged();
notifyObservers(Event.RUN);
}
/**
* 玩行为
*/
public void playAction() {
System.out.println("犯罪嫌疑人 玩");
setChanged();
notifyObservers(Event.PLAY);
}
}
2. 定义两个观察者,警察A 警察 B
public class PoliceA implements Observer {
/**
* 产生反应
*
* @param o 源、即被观察者
* @param arg event事件
*/
@Override
public void update(Observable o, Object arg) {
if (arg instanceof Event) {
Event event = (Event) arg;
System.out.println("Police A: receive event " + event.name());
if (event == Event.RUN) {
System.out.println("Police A: 守住A口");
} else if (event == Event.PLAY) {
System.out.println("Police A: 他要玩让他玩吧");
}
}
}
}
public class PoliceB implements Observer {
/**
* 产生反应
*
* @param o 源、即被观察者
* @param arg event事件
*/
@Override
public void update(Observable o, Object arg) {
if (arg instanceof Event) {
Event event = (Event) arg;
System.out.println("Police B: receive event " + event.name());
if (event == Event.RUN) {
System.out.println("Police B: 守住B口");
} else if (event == Event.PLAY) {
System.out.println("Police B: 他要玩让他玩吧");
}
}
}
}
3. 测试
public static void main(String[] args) {
BadMan badMan = new BadMan();
badMan.addObserver(new PoliceA());
badMan.addObserver(new PoliceB());
badMan.playAction();
badMan.runAction();
}
运行效果
犯罪嫌疑人 玩
Police B: receive event PLAY
Police B: 他要玩让他玩吧
Police A: receive event PLAY
Police A: 他要玩让他玩吧
犯罪嫌疑人 逃跑
Police B: receive event RUN
Police B: 守住B口
Police A: receive event RUN
Police A: 守住A口