行为型 观察者模式 (上)(文末有项目连接)

1:观察者模式 入门理解
观察者模式(Observer Design Pattern)也被称为发布订阅模式(Publish-Subscribe Design Pattern)。
在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。

被依赖的对象叫作被观察者(Observable),依赖的对象叫作观察者(Observer)。
也有以下叫法:
Subject-Observer、Publisher-Subscriber、Producer-Consumer、EventEmitter-EventListener、Dispatcher-Listener
2:经典代码流程
   1:设置 发布者订阅者   模块方法  Observer Subject
   2:创建 发布者订阅者   实现类  ConcreteSubject  ConcreteObserver
   3:订阅者 注册到发布者上 表示监听发布者
   4:给发布者发送消息  然后监听该发布者的所有订阅者 都能收到
1:发布者 与 订阅者 抽象类
public interface Publisher {
    //注册订阅者
    void registerObserver(Observer observer);

    //移除订阅者
    void removeObserver(Observer observer);

    //给所有发布者发布消息
    void notifyObserversSuccess(String message);

    //一次性注册所有发布者(可以不用
    void registerAllObserver(List observers);
}
public interface Observer {

    void success(String message);
}
2:发布者 与 订阅者 实现类
public class ConcretePublisher implements Publisher {

    private List observers = new ArrayList();

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        observers.remove(observer);
    }

    //    同步阻塞
    @Override
    public void notifyObserversSuccess(String message) {
        for (Observer observer : observers) {
            observer.success(message);
        }
    }

    @Override
    public void registerAllObserver(List observers) {
        this.observers = observers;
    }
}
// ConcreteObserverOne  ConcreteObserverTwo   ConcreteObserverRemove (重复3次 修改类名为以下即可)
public class ConcreteObserver implements Observer{

    @Override
    public void success(String message) {
        //可以根据 发布者的消息 执行自己的逻辑
        System.out.println("ConcreteObserver is success." + message);
    }
}
3:调用者
    //一个个进行订阅者进行新增
    private static void testObserverAdd() {
        ConcretePublisher subject = new ConcretePublisher();
        
        subject.registerObserver(new ConcreteObserverOne());
        subject.registerObserver(new ConcreteObserverTwo());

        ConcreteObserverRemove concreteObserverRemove = new ConcreteObserverRemove();
        subject.registerObserver(concreteObserverRemove);
   
        subject.removeObserver(concreteObserverRemove);

        subject.notifyObserversSuccess("ObserverAdd 成功了");
    }

    //一次性注册全部订阅者
    private static void testObserverAll() {
        ConcretePublisher subject = new ConcretePublisher();

        List observers = new ArrayList<>();
        observers.add(new ConcreteObserverOne());
        observers.add(new ConcreteObserverTwo());

        ConcreteObserverRemove concreteObserverRemove = new ConcreteObserverRemove();
        observers.add(concreteObserverRemove);
        subject.registerAllObserver(observers);
        
        subject.removeObserver(concreteObserverRemove);
        
        subject.notifyObserversSuccess("ObserverAll  成功了");
    }

3:基于不同应用场景的不同实现方式
观察者模式的应用场景非常广泛,小到代码层面的解耦,大到架构层面的系统解耦,再或者一些产品的设计思路,
都有这种模式的影子,比如,邮件订阅、RSS Feeds(站点共享),本质上都是观察者模式。

应对于普通的请求:
同步阻塞的实现方式:发布者和订阅者代码在同一个线程内执行,
发布者一直阻塞,直到所有的订阅者代码都执行完成之后,才执行后续的代码。

应对于频繁的请求:
异步非阻塞的实现方式:
    方法1:在订阅者的方法中,使用一个新的线程执行代码
    方法2:基于 EventBus 来实现

了解:
如果还需要请求第三方平台(即进程外),那么还可以沿用上面的逻辑,或者用一种更优雅的方式:
基于消息队列实现(解耦更彻底),但增加了维护成本
4:同步阻塞 和 异步非阻塞 对比
    //    同步阻塞
    @Override
    public void notifyObserversSuccess(String message) {
        for (Observer observer : observers) {
            observer.success(message);
        }
    }

    //    异步非阻塞 新增线程
    @Override
    public void notifyObserversSuccess(String message) {
        for (Observer observer : observers) {
            Thread thread = new Thread(() -> {
                observer.success(message);
            });
            thread.start();
        }
    }

  //  创建线程池
   private static  ThreadPoolExecutor threadPoolExecutor = 
   new ThreadPoolExecutor(4, 4, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024));

    //    异步非阻塞 新增线程池
    @Override
    public void notifyObserversSuccess(String message) {
        for (Observer observer : observers) {
            threadPoolExecutor.execute(() -> observer.success(message));
        }
    }
第一种实现方式,频繁地创建和销毁线程比较耗时,并且并发线程数无法控制,创建过多的线程会导致堆栈溢出。
第二种实现方式,尽管利用了线程池解决了第一种实现方式的问题,但线程池、异步执行逻辑都耦合在了方法里了。

5:遗留问题
如果我们的需求更加极端一点,需要在同步阻塞和异步非阻塞之间灵活切换,那就要不停地修改 发布者类的代码
除此之外,如果在项目中,不止一个业务模块需要用到异步非阻塞观察者模式,那这样的代码实现也无法做到复用。

因此我们引入EventBus 框架

项目连接

请配合项目代码食用效果更佳:
项目地址:
https://github.com/hesuijin/hesujin-design-pattern
Git下载地址:
https://github.com.cnpmjs.org/hesuijin/hesujin-design-pattern.git

demo-study模块  下 behavior_design_pattern  observer包

你可能感兴趣的:(行为型 观察者模式 (上)(文末有项目连接))