行为型模式——观察者模式
2020-08-29 本文已影响0人
Doooook
观察者模式定义
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。UML结构图如下:

- Subject(主题):主题通常是由类实现的可观察的接口。应通知的观察者使用attach方法注册。当它们不再需要被告知变更时,使用detach方法取消注册。
- ConcreteSubject(具体主题):具体主题是一个实现主题接口的类。它处理观察者列表并更新它们的变化。
- Observer(观察者):观察者是一个由对象实现的接口,应该根据主题中的更改来进行更新。每个观察者都应该实现update方法,该方法通知它们新的状态变化。
- ConcreteObserver(具体观察者),实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协同。
应用实例
1. 主题Subject
职责很简单,就是定义谁能观察(attach方法),谁不能观察(detach方法),通知所有的被观察者,以及状态更新变化。
/**
* @author: Jay Mitter
* @date: 2020-08-29 11:19
* @description: 主题
*/
public interface Subject {
/**
* 增加一个观察者(注册)
*
* @param observer
*/
void attach(AbstractObserver observer);
/**
* 删除一个观察者(取消注册)
*
* @param observer
*/
void detach(AbstractObserver observer);
/**
* 通知所有观察者
*/
void notifyObservers();
/**
* 设置状态
* @param action
*/
void setAction(String action);
/**
* 获取状态
* @return 状态
*/
String getAction();
}
2. 抽象观察者Observer
Observer是一个抽象类,包含姓名和主题属性
/**
* @author: Jay Mitter
* @date: 2020-08-29 11:20
* @description: 观察者抽象类
*/
public abstract class AbstractObserver {
protected String name;
protected Subject subject;
public AbstractObserver(String name, Subject subject) {
this.name = name;
this.subject = subject;
}
/**
* 更新
*/
abstract void update();
}
3. 具体通知者Secretary
Secretary秘书实现Subject接口,通知观察者
/**
* @author: Jay Mitter
* @date: 2020-08-29 11:26
* @description: 具体主题(秘书),实现Subject接口,在这里实现具体业务,在具体项目中,该类会有很多变种。
*/
public class Secretary implements Subject {
/**
* 观察者数组
*/
private List<AbstractObserver> observerList = new LinkedList<>();
private String action;
@Override
public void attach(AbstractObserver observer) {
this.observerList.add(observer);
}
@Override
public void detach(AbstractObserver observer) {
this.observerList.remove(observer);
}
@Override
public void notifyObservers() {
for (AbstractObserver observer : observerList) {
observer.update();
}
}
@Override
public void setAction(String action) {
this.action = action;
}
/**
* 前台状态
* @return 状态
*/
@Override
public String getAction() {
return action;
}
}
4. 具体观察者StockObserver
看股票的同事,继承AbstractObserver类
/**
* @author: Jay Mitter
* @date: 2020-08-29 11:29
* @description: 看股票的同事
*/
public class StockObserver extends AbstractObserver {
public StockObserver(String name, Subject subject) {
super(name, subject);
}
@Override
void update() {
System.out.println(subject.getAction() + "\n" + name + " 关闭股票行情,继续工作");
}
}
5. 具体观察者NBAObserver
看NBA的同事,继承AbstractObserver类
/**
* @author: Jay Mitter
* @date: 2020-08-29 11:29
* @description: 看NBA的同事
*/
public class NBAObserver extends AbstractObserver {
public NBAObserver(String name, Subject subject) {
super(name, subject);
}
@Override
void update() {
System.out.println(subject.getAction() + "\n" + name + " NBA停摆了,继续工作");
}
}
测试
/**
* 行为型模式——观察者模式
*/
@Test
public void testBehaviorObserver() {
// 创建一个主题
Secretary secretary = new Secretary();
// 定义一个观察者
StockObserver stockObserver = new StockObserver("adam", secretary);
NBAObserver nbaObserver = new NBAObserver("tom", secretary);
// attach方法注册,相当于订阅消息
secretary.attach(stockObserver);
secretary.attach(nbaObserver);
// 状态改变
secretary.setAction("小心,Boss回来了");
// 发通知
secretary.notifyObservers();
// nbaObserver被移除通知队列,状态发生变化时tom不再受到通知
secretary.detach(nbaObserver);
secretary.setAction("小心,Boss又回来了");
secretary.notifyObservers();
}
结果:
小心,Boss回来了
adam 关闭股票行情,继续工作
小心,Boss回来了
tom NBA停摆了,继续工作
小心,Boss又回来了
adam 关闭股票行情,继续工作