20. 23种经典设计模式-34-观察者模式

1. 观察者模式(Observer Pattern)

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically. (定义对象间一种一对多的依赖关系, 使得当一个对象状态发生改变时,所有依赖于它的对象都会接收到通知并被自动更新)

观察者模式也称之为发布订阅模式, 也是一种项目中常用的设计模式.

1.1 观察者模式-核心思想

  • 其实就是消息发布订阅模式
  • 实现被观察者和观察者直接的解耦:
    • 被观察者无须关注有哪些观察者,也不用关心观察者具体实现逻辑.
    • 观察者无须关注什么时候,什么场景状态发生了变更,只需要等待消息变更通知即可.

1.2 观察者模式-类图

观察者模式有四种角色:

  • Subject: 被观察者角色: 能够动态地管理(添加和删除)观察者, 通知观察者。通常为抽象类或接口.
  • Observer: 观察者抽象接口, 定义更新方法.
  • ConcreteSubject: 具体被观察者角色. 定义自己的业务逻辑,并实现哪些操作触发通知方法
  • ConcreteObserver: 具体观察者.
    • 维护一个指向ConcreteObserver 的引用, 当接收到通知时, 进行状态实时查询
    • 实现更新接口

[外链图片转存失败(img-go3w6h6a-1566895375964)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-observer-01.png)]

1.3 观察者模式-时序图

  1. 触发更新状态方法: 标准观察者模式中, 观察者持有具体被观察者对象的引用ConcreteSubject, 因此也可以执行修改状态方法. 第1步也可以是其它客户端触发修改状态方法
  2. 通知方法: 修改状态方法内部触发通知观察者方法
  3. 按顺序同步执行第一个观察者的更新方法
  4. 观察者更新方法中,通过持有的具体观察者引用对象来查询最新的状态
  5. 返回给观察者当前状态,观察者自行处理
  6. 通知第二个观察者执行更新状态…

1.4 观察者模式-优缺点

  • 优点:
    • 被观察者与观察者直接松耦合. 标准模式中观察者中需要耦合具体被观察者引用.
    • 建立了一套触发机制. 可实现消息广播机制
  • 缺点:
    • 消息触发时,同步执行,会有效率,异常等问题. 可考虑采取异步通知解决
    • 并发问题. 观察者中接收到消息时,需要实时查询被观察者的状态,在多线程环境中,会导致并发问题.

1.5 观察者模式-适用场景

  • 消息通知, 事件响应.
  • 消息订阅,发布.
  • 一个对象的变更需要通知多个对象,但是不知道具体通知的对象有哪些

1.6 注意事项

  • 通知方法是按顺序执行,需要考虑效率和异常情况
  • 任何一个观察者的更新方法出现问题时,都可能导致业务逻辑执行失败。可考虑异步线程

2. 观察者模式-应用示例

我们来假定一种应用场景,App和Web同时监听温度的变化.

2.1 类图

[外链图片转存失败(img-JqVB4GfL-1566895375966)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-observer-03.png)]

2.2 抽象被观察者-AbsSubject

  • 从观察者模式标准类图来看,抽象被观察者角色应该是一个抽象类.因此笔者也采用抽象类来实现.
  • 如果替换为接口会更灵活,更通用. 存储和遍历观察者的逻辑由子类实现
public abstract class AbsSubject {

    // 储存所有的观察者
    private LinkedList<Observer> observers = new LinkedList();

    public void attach(Observer observer){
        this.observers.add(observer);
    }

    public void detach(Observer observer){
        this.observers.remove(observer);
    }

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

2.3 具体被观察者-TemperatureSubject

  • 监听状态为温度
  • 当修改温度时,通知所有观察者
public class TemperatureSubject extends AbsSubject {

    // 保存当前温度
    private String temperature;

    public void setTemperature(String temperature) {
        this.temperature = temperature;

        System.out.println("更新当前温度为:" + temperature + " 度");

        // 通知观察者
        this.notifyObservers();
    }

    public String getTemperature() {
        return this.temperature;
    }
}

2.4 抽象观察者-Observer

public interface Observer {

    // 更新方法: 接收到通知后, 进行更新操作
    public void update();
}

2.5 web应用观察者-WebObserver

当接收到应用时,会去查询实时状态, 会保证应用获取到真实的温度.

public class WebObserver implements Observer {

    private TemperatureSubject concreteSubject;

    public WebObserver(TemperatureSubject subject) {
        this.concreteSubject = subject;
    }

    @Override
    public void update() {

        System.out.println("Web-接收到消息...");

        // 查询状态
        String state = concreteSubject.getTemperature();
        System.out.println("Web-查询实时温度:" + state + " 度\n");
    }
}

2.6 app 应用观察者-AppObserver

public class AppObserver implements Observer {

    private TemperatureSubject concreteSubject;

    public AppObserver(TemperatureSubject subject) {
        this.concreteSubject = subject;
    }

    @Override
    public void update() {

        System.out.println("App-接收到消息...");

        // 查询状态
        String state = concreteSubject.getTemperature();
        System.out.println("App-查询实时温度:" + state + " 度\n");
    }
}

2.7 测试

@Test
public void test() {

    // 创建监听主题
    TemperatureSubject temperatureSubject = new TemperatureSubject();

    // 添加观察者
    temperatureSubject.attach(new WebObserver(temperatureSubject));
    temperatureSubject.attach(new AppObserver(temperatureSubject));

    // 更新状态
    temperatureSubject.setTemperature("37");

}

2.8 测试输出

更新当前温度为:37 度
Web-接收到消息...
Web-查询实时温度:37 度

App-接收到消息...
App-查询实时温度:37 度
发布了321 篇原创文章 · 获赞 676 · 访问量 147万+

猜你喜欢

转载自blog.csdn.net/zongf0504/article/details/100103558
今日推荐