观察者模式之我的理解

Posted aofengdaxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了观察者模式之我的理解相关的知识,希望对你有一定的参考价值。

先来看一个场景

在很多业务中都存在一个流程类型的业务。比如一个在线商城系统下单操作,可能包含有以下几个流程:

  1. 检查库存
  2. 扣减库存
  3. 生成订单
  4. 通知用户
  5. 通知商家

简单的实现方法

最直接和简单的方法,就是根据现在业务的需要,我们在下单的这个操作中去调用库存检查、库存剪口、订单生成、用户通知、商家通知等API。然后搞定。

存在的问题

这种方法的问题在于,如果我们需要在某个流程中添加一个新的操作,
比如在扣减库存之后,我们需要添加一个操作,就是将库存扣减的结果写入到一个日志文件中。
那么我们就需要修改下单的这个操作,将这个操作加入到下单的操作中。
这样就会导致下单的这个操作变得越来越复杂,不利于维护。
这样的代码会变得难以维护,也不利于扩展。如何解耦这些流程与下单的操作,更好的方便拥抱变化呢?观察者模式就可以解决这么一个问题。

解决方式

我们可以采用观察者模式来解决这个问题。观察者模式的定义如下:
观察者模式(Observer Pattern):又可以称为订阅-发布模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
在上述的场景中,我们可以将下单操作作为一个主题,库存检查、库存扣减、订单生成、用户通知、商家通知等操作作为观察者。当下单操作发生时,所有的观察者都会收到通知,然后执行自己的操作。
这样当需要增加或者移除流程时,就不需要修改下单操作,只需要增加或者移除观察者的列表即可。可以很方便地解决需求的变化。

观察者模式类图表示

observes 1 * notifies 1 * Subject +attach(observer:Observer) +detach(observer:Observer) +notify() ConcreteSubject +state:string +getState() +setState(state:string) Observer +update(subject:Subject) ConcreteObserver +observerState:string +update(subject:Subject)

简单的理解

  1. 观察者继承观察者接口,实现update方法。
  2. 被观察者继承被观察者接口,实现attach、detach、notify方法。
  3. 被观察者持有观察者的列表,当被观察者发生变化时,会通知所有的观察者。
  4. 被观察者的变化会触发观察者的update方法,观察者可以根据自己的需求来实现update方法。

代码实现

观察者接口

//观察者接口
public interface Observer 
    void update(Subject subject);

//被观察者接口
public interface Subject 
    void attach(Observer observer);

    void detach(Observer observer);

    void notifyObservers();


public class OrderService implements Subject 
    private List<Observer> observers = new ArrayList<>();

    public void attach(Observer observer) 
        observers.add(observer);
    

    public void detach(Observer observer) 
        observers.remove(observer);
    

    public void notifyObservers() 
        for (Observer observer : observers) 
            observer.update(this);
        
    

    public void createOrder() 
        System.out.println("创建订单");
        notifyObservers();
    


public class ObserverOne implements Observer 
    public void update(Subject subject) 
        System.out.println("观察者收到通知,执行自己的操作");
    

public class ObserverTest 
    public static void main(String[] args) 
        OrderService orderService = new OrderService();
        ObserverOne observerOne = new ObserverOne();
        orderService.attach(observerOne);
        orderService.createOrder();
    

优缺点

优点

  1. 观察者和被观察者之间是抽象耦合的。
  2. 建立一套触发机制。
  3. 观察者模式支持广播通信。
  4. 观察者模式符合“开闭原则”。

缺点

  1. 如果一个被观察者有很多直接和间接的观察者时,将所有的观察者都通知到会花费很多时间。
  2. 如果在观察者和被观察者之间有循环依赖,观察者会等待被观察者处理完再处理,将导致系统崩溃。
  3. 观察者之间有过多的细节依赖,提高时间消耗及程序复杂度。

应用场景

  1. 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
  2. 事件多级触发场景。
  3. 跨系统的消息交换场景,如消息队列的处理机制。

以上是关于观察者模式之我的理解的主要内容,如果未能解决你的问题,请参考以下文章

观察者模式之我的理解

工厂模式 ioc dom4j 反射之我的一点理解

观察者模式

设计模式之观察者模式

深入理解观察者模式

对观察者模式的理解