观察者模式


设计模式之观察者模式

观察者模式的定义是一个一对多的依赖关系,让一个或多个观察者对象监控一个主题对象。当主题对象在状态上发生变化时,能够通知所有依赖此主题的观察者对象,使这些观察者对象能够处理此次更新

参与对象

  • 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());

总结

观察者模式适用于一个事件的发生会启动多个事件的响应。如果在源事件中依次调用启动关联事件的,这样每次增加关联事件都会在源事件中进行同步修改。一个动作可能会影响多个关联动作的场景适用于观察者模式,例如在一个系统中业务执行完毕后会触发下游多个业务的场景(电商中的订单付款成功就会触发下游物流、商品、财务等多个系统)


  TOC