设计模式之观察者模式
观察者模式的定义是一个一对多的依赖关系,让一个或多个观察者对象监控一个主题对象。当主题对象在状态上发生变化时,能够通知所有依赖此主题的观察者对象,使这些观察者对象能够处理此次更新
参与对象
- Subject
- Observer
- Client
Subject
主题对象主体是基于被观察者,并且在内部保存一个或多个被观察者的处理对象
Observer
Observer对象是抽象出来对事件进行处理的对象
client
客户端对象的作用是触发事件的发生,并且将观察者注册到被观察者中
使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
基本的观察者模式
- Subject
public class Subject {
private List<Observer> observerList = Lists.newArrayList();
private Integer state;
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
this.notifyAllObservers();
}
public void attach(Observer observer){
observerList.add(observer);
}
private void notifyAllObservers(){
for (Observer observer : observerList) {
observer.update();
}
}
}
- Observer
public interface Observer {
default void update(){
System.out.println(Thread.currentThread().getName() + ":开始执行...");
}
}
public class ObserverImpl implements Observer {
@Override
public void update(){
System.out.println(Thread.currentThread().getName() + ":开始执行ObserverImpl...");
}
}
public class ObserverImpl2 implements Observer {
@Override
public void update(){
System.out.println(Thread.currentThread().getName() + ":开始执行ObserverImpl2...");
}
}
- client
public class ObserverClient {
public static void main(String[] args){
Subject subject = new Subject();
Observer observer1 = new ObserverImpl();
Observer observer2 = new ObserverImpl2();
subject.attach(observer1);
subject.attach(observer2);
subject.setState(1);
}
}
Guava中的观察者模式(EventBus)
- Observer
public static class Event {
public void action() {
System.out.println("执行事件...")
}
}
- Subject
public static class EventListener {
@Subscribe
@AllowConcurrentEvents
public void onEvent(Event1 event1) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->异步消费订阅事件,接收到:" + event1);
}
@Subscribe
public void onEvent(Event2 event2) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->同步消费订阅事件,接收到:" + event2);
}
@Subscribe
public void onEvent(DeadEvent deadEvent) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->订阅错误的事件,接收到:" + deadEvent);
}
}
- client
EventBus ebSyc = new EventBus();
//注册监听器
ebSyc.register(new EventListener());
//执行相应事件
ebSyc.post(new Event2());
总结
观察者模式适用于一个事件的发生会启动多个事件的响应。如果在源事件中依次调用启动关联事件的,这样每次增加关联事件都会在源事件中进行同步修改。一个动作可能会影响多个关联动作的场景适用于观察者模式,例如在一个系统中业务执行完毕后会触发下游多个业务的场景(电商中的订单付款成功就会触发下游物流、商品、财务等多个系统)