设计者模式之观察者模式
模式描述
角色
- 抽象主题(Subject)角色:它是一个抽象类或接口,提供了添加、删除观察者的方法,与通知观察者进行变更的方法
- 具体主题(Concrete Subject)角色:具体实现类
- 抽象观察者(Observer)角色:它是一个抽象类或接口,提供了观察者变更的方法
- 具体观察者(Concrete Observer)角色:具体实现类
特征
- 针对一对多模式下的松耦合
- 做到及时通讯效果(目标与观察者之间建立了一套触发机制)
- 观察者多的情况下,及时通讯效率会有所下降。观察者会被放到 Collection 集合中。
场景
多用于单一应用下的系统逻辑,在 Spring 源码中就用到观察者模式。对于跨系统间通讯不适合。
模式实现
1、被观察者
/*
* 被观察者,
* 我作为 微信公众号,允许用户进行订阅与取消订阅
* 同时,我可以为订阅者,推送消息
*/
public interface Subject {
// 添加订阅关系
void attach(Observer observer);
// 移除订阅关系
void detach(Observer observer);
// 通知订阅者
void notifyObservers(String message);
}
2、具体被观察者
public class ConcreteSubject implements Subject{
// 订阅者容器(list、map 都可以)
private List<Observer> observers = new ArrayList<Observer>();
@Override
public void attach(Observer observer) {
// 添加订阅关系
observers.add(observer);
}
@Override
public void detach(Observer observer) {
// 移除订阅关系
observers.remove(observer);
}
@Override
public void notifyObservers(String message) {
// 通知订阅者
for (Observer observer : observers) {
observer.update(message);
}
}
}
3、观察者
/**
* 观察者模式
* 我作为微信用户,会实时获取到微信公众号推送的各种消息
*/
public interface Observer {
//更新方法
public void update(String message);
}
4、具体观察者
public class ConcreteObserver implements Observer{
@Override
public void update(String message) {
// 模拟处理业务逻辑
System.out.println("用户收到消息:" + message);
}
}
5、测试
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
// 这里假设是增加新用户
subject.attach(new ConcreteObserver());
ConcreteObserver twoObserver = new ConcreteObserver();
subject.attach(twoObserver);
// 发送朋友圈动态
subject.notifyObservers("第一条消息");
subject.detach(twoObserver);
subject.notifyObservers("第二个消息");
}
}
运行结果
用户收到消息:第一条消息
用户收到消息:第一条消息
用户收到消息:第二个消息
Spring 源码中的应用
观察者模式 与 发布订阅模式
关注点:
- 推送是 主动的。
- 渠道可以是多个,发布者发布多个,订阅者订阅多个。
- 发布订阅模式,可以认为包含观察者模式。subject <==> channel