Featured image of post 观察者模式

观察者模式

观察者模式是一种行为型模式

观察者模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,其他所有依赖的对象都会得到通知,并自动更新。

观察者模式又称为「发布-订阅模式」Publish-Subscribe,是一种通知机制,让发送通知的一方(被观察者)和接收通知的一方(观察者)彼此分离,互不影响。

常见的场景:

  • 🔖 比如 Github 的 Actions,其实就是观察者模式的一种体现,当我们根据规则进行了一些 git 操作后,Github Actions 会根据配置做一些操作,比如编译/检查格式等。

🎈 实现方式

  • 🎗️ 「发布者」添加订阅机制,可以控制对象订阅与取消订阅事件

    • 一个用于存储订阅者的 List 成员变量
    • 用于添加/删除的公有方法
    • 当发生发布者事件时,通过遍历订阅者并调用对象特定的通知方法

  • 🎗️ 「订阅者」实现统一的接口,发布者仅通过该接口与订阅者交互
    • 通常会有对各订阅者跟踪一个发布者的事件,实现统一接口防止耦合
    • 在接口中声明通知方法及其参数

⚠ 注意事项:

  • 顺序执行通知时,可能会因为某一观察者导致卡壳,通常会采用异步的方式执行任务。

🛠️ 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Store {

    private Map<String, Product> products = new HashMap<>();

    // 希望订阅新上架的商品的人
    private List<ProudctObserver> observers = new ArrayList<>();

    public boolean addObserver(ProudctObserver pb) {
        this.observers.add(pb);
    }

    pubilc boolean removeObserver(ProductObserver pb) {
        return this.observers.remove(pb);
    }

    // 发布新商品
    public void addNewProduct(String name, BigDecimal price) {
        Product p = new Product(name, price);
        products.put(name, p);

        // 📧 通知观察者
        observers.forEach(o -> o.onPublished(p));
    } 

    // 更新商品价格
    public void setProductPrice(String name, double price) {
        Product p = products.get(name);
        p.setPrice(price);
        
        // 📧 通知观察者
        observers.forEach(o -> o.onPriceChanged(p));
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 被观察者实现统一的接口
interface ProductObserver {
    void onPublished(Product product);
    void onPriceChanged(Product product);
}

// 观察者对象
class Customer implements ProdcutObserver {
    // ...
}

class Admin implements ProductObserver {
    // ...
}
1
2
3
4
5
6
7
// observer 观察者
Admin admin = new Admin();
Customer customer = new Customer();

// 注册观察者
store.addObserver(admin);
store.addObserver(customer);