observer

第二十一章 观察者模式(Observer Pattern)

1 概要

观察者模式(Observer Pattern)是一种行为模式(Behavior Design Patters)。观察者模式建立了对象之间的依赖关系(Dependency);一旦一个对象的状态发生变化,观察者模式能够通知依赖对象。在观察者模式下,一个对象可以同时"观察"多个对象;一个对象也可以同时被多个对象"观察"。

观察者模式的应用场景非常广。一个常见的例子是,在一个电子商务网站上,用户可以将商品添加入购物车(但未购买)。当商品的数量或者价格发生变化时,系统会通知这些用户,告知数量和价格的变更。

2 观察者模式的结构

在观察者模式中,有四个参与方。

  1. Subject接口定义了数据变更的接口。一旦这些接口被调用,我们可以认定Subject的对象发生了变化。
  2. ConcreteSubject类是Subject接口的一个具体实现。
  3. Observer定义了"观察"Subject对象状态变更的接口。
  4. ConcreteObserver类实现了Observer接口。当Subject对象发生变更时,ConcreteObserver会进行相应的处理。

图一 观察者模式结构

图一 观察者模式结构。

3 观察者模式示例

我们使用一个简单的用例来展示观察者模式的用法。这个用例实现了一个简单的,跟踪商品价格的功能。当商品的价格发生变化时,系统会通知用户。

我们首先定义一个Subject接口,用于定义观察者注册(registerObserver)和注销(removeObserver)接口,通知用户接口(notify)和设置价格接口(setPrice)。在Product类中实现了这些接口。Product对象将所有关心该商品价格的用户放置在一个链表中(observers)。当价格发生变化后,通知所有注册了的用户。

interface Subject {
    public void registerObserver(Observer observer);
    public void removeObserver(Observer observer);
    public void notify();
    public void setPrice(double newPrice);
}

public class Product implements Subject {
    private ArrayList<Observer> observers = null;
    private String name = null;
    private double price;
    

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
        this.observers = new ArrayList<>();
    }

    @Override
	public void registerObserver(Observer observer) {
        observers.add(observer);
    }
    
    @Override
	public void removeObserver(Observer observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notify() {
        for(Observer observer: observers) {
            observer.update(this.name, this.price);
        }
    }

    @Override
    public void setPrice(double newPrice) {
        this.price = newPrice;
        this.notify();
    }
}

然后,我们定义观察者接口Observer,它只有一个成员方法update()。User类实现了Observer接口,在update()方法中实现处理新价格的逻辑。

interface Observer {
    public void update(String productName, double productPrice);
}

public class User implements Observer {
    @Override
    public void update(String productName, double productPrice) {
        // 收到了商品新的价格
    }
}

最后,我们在ObserverPatternExample类中展示观察者模式的使用方法。首先,我们创建了两个用户UserA和UserB,和两个商品productA和productB。然后,将关心商品价格的用户注册到该商品中。最后,在修改商品的价格的同时,该程序会通知相应用户新的商品价格。

public class ObserverPatternExample {
    public static void main(String[] args) {
        User userA = new User();
        User userB = new User();

        Product productA = new Product("Book", 10.0);
        productA.registerObserver(userA);
        productA.registerObserver(userB);

        Product productB = new Product("Magazine", 15.0);
        productB.registerObserver(userA);

        productA.setPrice(10.5); // 会通知userA和userB新的商品价格

        productB.setPrice(14.5); // 会通知userA新的商品价格
    }
}

4 小结

本章介绍了观察者模式的结构和使用方法。观察者模式将事件的发生对象与接收对象分离开,使得开发人员可以专注于事件的触发逻辑和事件的响应逻辑。另外,从代码中可以看出,在事件发生时,观察者模式是依次通知观察者的。因此,在使用观察者模式时可能会出现一个观察者已经被通知,而另一个却尚未被通知的情况。

上一章
下一章

注册用户登陆后可留言

Copyright  2019 Little Waterdrop, LLC. All Rights Reserved.