前端设计模式(观察者) | 青训营

92 阅读2分钟

1、动机

在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系” ——一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,这些对象做出相应反应。使用面向对象技术,可以使这种依赖关系不那么紧密(松耦合)。

2、定义

  1. 定义了对象之间一种一对多的依赖关系,以便当一个 对象(Subject)的状态发生改变时,所有依赖于它的对象都得到通知(被动接受)并自动更新(主动订阅)
  2. 发生改变的对象称为观察目标(发送者,一个),被通知的对象称为观察者(订阅者,多)
  • 发送者:红绿灯信号

  • 订阅者:司机

  • 被动接受:信号灯让司机看到

  • 主动订阅:司机可以选择无视红路灯信号,也可以主动接受这个信号

3、结构

  1. Subject(目标):它是指被观察的对象。在目标中定义了一个观察者集合;提供一系列方法来增加和删除观察者对象;同时定义了通知方法Notify() 。(目标类可以是接口, 也可以是抽象类或具体类。)
  2. ConcreteSubject(具体目标):如果无须扩展目标类,具体目标类则可以省略。
  3. Observer(观察者):观察者将对观察目标的改变做出反应, 观察者一般定义为接口, 该接口声明了更新数据的方法Update() , 因此又称为抽象观察者。
  4. ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的
  5. Update() 方法。通常在实现时; 可以调用具体目标类的Attach() 方法将自己添加到目标类的集合中或通过Detach() 方法将自己从目标类的集合中删除。

image.png

4、TS举例

interface IObserver {
  nameChanged(newName: string): void;
}

class Test implements IObserver {
  nameChanged(newName: string): void {
    console.log("监听到变化,名字变更为" + newName);
  }
}

class Person {
  private _name!: string;
  // 所有的观察者组成一个数组
  observers: Array<IObserver> = new Array<IObserver>();

  set name(value: string) {
    this._name = value;
    // 发生变化
    // 遍历观察者数组,给所有观察者发消息
    for (let observer of this.observers) {
      observer.nameChanged(this._name);
    }
  }

  get name(): string {
    return this._name;
  }
}

let person = new Person();
let test = new Test();
// 设置为监听对象
person.observers.push(test);
// 做改变
person.name = "Alhaitham";

5、MVC

Observer模式是基于事件的UI框架中非常常用的设计模式,也是 MVC模式的一个重要组成部分。 其中, 模型(model)可对应于观察者模式中的又见察目标,而视图(View)对应于观察者,控制器(Controller)可充当两者之间的中介者。当模型层的数据发生改变时,视图层将自动改变其显示内容。