观察者模式
1.问题
订阅报纸的基本流程
- 首先按照自己的需要选择合适的报纸,具体的报刊杂志目录可以从邮局获取
- 选择好后,就到邮局填写订阅单,同时缴纳所需的费用
- 报社按照出报时间,通过邮局送到每个订阅者的手里
2.定义
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自动更新。
3.观察者模式的结构和说明
- Subject: 目标对象,通常具有如下功能。
- 一个目标可以被多个观察者观察
- 目标提供对观察者注册和退订的维护
- 当目标的状态发生变化时,目标负责通知所有注册的、有效的观察者。
- Observer: 定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,已获取目标对象的数据
- ConcreteSubject: 具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册的、有效的观察者,让观察者执行相应的处理。
- ConcreteObserver: 观察者的具体对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的对应状态一致。
观察者模式示例代码
(1). 目标对象定义代码:
/**
*目标队形作为被观察者
*/
public class Subject {
/**
* 用来保存注册的观察者对象,也就是报纸的订阅者
*/
private List<Observer> observerList = new ArrayList<>();
/**
* 报纸的读者需要向报社订阅,先要注册
* @param observer
*/
public void attach(Observer observer) {
observerList.add(observer);
}
/**
* 报纸的读者可以取消订阅
* @param observer
*/
public void detach(Observer observer) {
observerList.remove(observer);
}
/**
* 当每期报纸印刷出来后,就要迅速主动地被送到读者的手中
* 相当于通知读者,让他们知道
*/
protected void notifyObserverList() {
observerList.forEach(observer -> observer.update(this));
}
}
(2).目标对象代码:
public class ConcreteSubject extends Subject {
/**
* 示意,目标对象的状态
*/
private String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
/**
* 状态发生了改表,通知各个观察者
*/
this.notifyObserverList();
}
}
(3).观察者定义代码:
public interface Observer {
/**
* 更新接口
* @param subject
*/
public void update(Subject subject);
}
(4).观察者具体实现代码:
public class ConcreteObserver implements Observer {
/**
* 示意,观察者的状态
*/
private String observerState;
@Override
public void update(Subject subject) {
/**
* 具体的更新实现
* 这里可能需要更新观察者状态,使其与目标的状态保持一致
*/
observerState = ((ConcreteSubject) subject).getSubjectState();
}
}
4. 使用观察者模式实现示例
4.1. 被观察的目标
- 注册订阅者,也就是说很多个人来订报纸,报社肯定要有相应的记录才行。
- 出版报纸,这个是报社的主要工作。
- 发行报纸,也就是把出版的报纸发送到订阅者手中。
- 退订报纸,当订阅者不想继续订阅了,可以取消订阅。
被观察者定义
public class Subject {
/**
* 用来保存注册的观察者对象,也就是报纸的订阅者
*/
private List<Observer> observerList = new ArrayList<>();
/**
* 报纸的读者需要向报社订阅,先要注册
* @param observer
*/
public void attach(Observer observer) {
observerList.add(observer);
}
/**
* 报纸的读者可以取消订阅
* @param observer
*/
public void detach(Observer observer) {
observerList.remove(observer);
}
/**
* 当每期报纸印刷出来后,就要迅速主动地被送到读者的手中
* 相当于通知读者,让他们知道
*/
protected void notifyObserverList() {
observerList.forEach(observer -> observer.update(this));
}
}
目标实现
public class NewsPaper extends Subject {
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
this.notifyObserverList();
}
}
4.2 观察者
观察者定义
public interface Observer {
/**
* 更新接口
* @param subject
*/
public void update(Subject subject);
}
观察者实现
public class Reader implements Observer {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Subject subject) {
System.out.println(name + "收到报纸了,报纸的内容是:" + ((NewsPaper) subject).getContent());
}
}
报纸订阅客户端
public class NewsPaperClient {
public static void main(String[] args) {
NewsPaper newsPaper = new NewsPaper();
Reader reader01 = new Reader();
reader01.setName("张三");
Reader reader02 = new Reader();
reader02.setName("李四");
newsPaper.attach(reader01);
newsPaper.attach(reader02);
newsPaper.setContent("123");
}
}