设计模式之观察者模式-谈谈你对观察者模式的理解

615

定义

先来段wiki上面的定义:观察者模式是软件设计模式的一种。在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实时事件处理系统。简单来讲,就是定义了一组一对多的关系。当被观察者的状态改变,会通知观察者做出相应的动作。

在开发过程中,常常会遇到如下的场景:

  • 游戏开发中,当人物走到某个格子,触发加血、战斗等动作
  • 微信公众号,当用户关注了某公众号,一旦公众号更新了文章,便可以给用户进行推送

在这种情况下,我们该如何实现符合开闭原则的代码呢,观察者模式便是一个很好的选择。

模式结构及实现

下图便是观察者模式的模式结构。

观察者设计模式的结构

从图中可以看出,观察者模式主要结构主要包括发布者和订阅者两个行为对象,发布者持有所有订阅者的集合,当需要发布事件或者消息时,通知订阅者做出相应的动作。

代码

定义事件接口,作为观察者与被观察者之间交互的媒介

public interface Event {
}

定义Subscriber接口,作为观察者的接口

public interface Subscriber {

    void update(Event event);

}

Subscriber的两个简单实现类

public class ReadSubscriber implements Subscriber{
    @Override
    public void update(Event e) {
        System.out.println("ReadSubscriber");
    }
}
public class WriteSubscriber implements Subscriber{
    @Override
    public void update(Event e) {
        System.out.println("WriteSubscriber");
    }
}

定义Publisher接口,作为被观察者的接口

public interface Publisher {

    void subscribe(Subscriber subscriber);

    void unsubscribe(Subscriber subscriber);

    void notifySubscribers(Event event);

}

Publisher接口实现类

public class DefaultPublisher implements Publisher{

    private final List<Subscriber> subscribers = new ArrayList<>();

    @Override
    public void subscribe(Subscriber subscriber) {
        subscribers.add(subscriber);
    }

    @Override
    public void unsubscribe(Subscriber subscriber) {
        subscribers.remove(subscriber);
    }

    @Override
    public void notifySubscribers(Event event) {
        for(Subscriber subscriber:subscribers){
            subscriber.update(event);
        }
    }
}

Demo测试

public class Demo {
    public static void main(String[] args) {
        DefaultPublisher defaultPublisher = new DefaultPublisher();
        defaultPublisher.subscribe(new ReadSubscriber());
        defaultPublisher.subscribe(new WriteSubscriber());
        Event event = new Event() {
        };
        defaultPublisher.notifySubscribers(event);
    }
}

结果

ReadSubscriber
WriteSubscriber

观察者模式的优缺点

优点:

  • 符合开闭原则,降低了模块之间的耦合,方便根据业务进行扩展
  • 可以在运行时进行动态改变观察者集合

缺点:

  • 当被观察者持有了大量的观察者,会导致事件的发布变得耗时

注意事项

  • 一般采用异步的方式,一方面提高系统响应时间,另一方面防止由于某个观察者出现错误而导致事件发布卡壳,乃至失败
  • 防止循环依赖(如果观察者与被观察者之间有循环依赖的话,将会导致互相调用,致使系统崩溃)

具体应用

Spring中的应用

在spring中,事件的订阅与发布使用到了观察者模式

通过ApplicationEventApplicationListenerApplicationContextApplicationEventMulticaster四个组件实现了项目中最常使用的事件监听器。具体代码可参照源码,再次不做扩展了。