观察者模式之我的理解

先来看一个场景

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

  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. 跨系统的消息交换场景,如消息队列的处理机制。

猜你喜欢

转载自blog.csdn.net/aofengdaxia/article/details/128787083