第九章 设计模式 - 行为型 - 观察者模式 【发布-订阅模式】

观察者模式概念

1、观察者模式又叫 发布-订阅 模式,其用来定义对象之间的一对多依赖关系,以便当一个对象更改状态时,将通知其所有依赖关系

2、观察者模式 具备两个角色,即 发布者 和 订阅者。

3、正如我们工作中的产品经理就是一个 “ 发布者 ”,而前后端、测试可以理解为 “ 订阅者 ”

4、在 JavaScript 中,我们一般用 事件模型 来替代传统的 发布-订阅模式

5、观察者模式 定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使它们能够自动更新自己,当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。

观察者模式的运用

其实观察者模式对于前段来说应用很广,一个普通dom绑定一个事件其实也算观察者模式,区别就在于你能否在这模式核心基础上考虑到更多的东西,而不单单仅仅的发布监听。

Vue,React等等框架都大范围使用了这种设计模式,优点很明显

  1、一是时间解耦
  
  2、二是对象之间的解耦
  
  3、但是无论是啥模式都会有缺点,观察模式如果过度使用,会造成对象代码关联弱化,导致程序代码难以理解于跟踪维护

观察者模式的场景运用示例 Vue Event Bus

import Vue from 'vue';

const EventBus = new Vue();
Vue.prototype.$bus = EventBus;

// 订阅事件
this.$bus.$on('testEvent', func);
// 发布/触发事件
this.$bus.$emit('testEvent', params);

观察者模式的代码示例其一

// 定义发布者类
class Publisher {
  constructor () {
    this.observers = [];
    this.prdState = null;
  }
  
  // 增加订阅者
  add (observer) {
    this.observers.push(observer);
  }
  
  // 通知所有订阅者
  notify () {
    this.observers.forEach((observer) => {
      observer.update(this);
    })
  }
  
  // 该方法用于获取当前的 prdState
  getState () {
    return this.prdState;
  }

  // 该方法用于改变 prdState 的值
  setState (state) {
    // prd 的值发生改变
    this.prdState = state;
    // 需求文档变更,立刻通知所有开发者
    this.notify();
  }
}

// 定义订阅者类
class Observer {
 	constructor () {
		this.prdState = {};
  }
  
  update (publisher) {
    // 更新需求文档
    this.prdState = publisher.getState();
    // 调用工作函数
    this.work();
  }
  
  // work 方法,一个专门搬砖的方法
  work () {
    // 获取需求文档
    const prd = this.prdState;
    console.log(prd);
  }
}

// 创建订阅者:前端开发小王
const wang = new Observer();

// 创建订阅者:后端开发小张
const zhang = new Observer();

// 创建发布者:产品经理小曾
const zeng = new Publisher();

// 需求文档
const prd = {
  url: 'xxxxxxx'
};

// 小曾开始拉人入群
zeng.add(wang);
zeng.add(zhang);

// 小曾发布需求文档并通知所有人
zeng.setState(prd);

观察者模式的代码示例其二

// 主题 保存状态,状态变化之后触发所有观察者对象
class Subject {
  constructor() {
    this.state = 0
    this.observers = []
  }
  getState() {
    return this.state
  }
  setState(state) {
    this.state = state
    this.notifyAllObservers()
  }
  notifyAllObservers() {
    this.observers.forEach(observer => {
      observer.update()
    })
  }
  attach(observer) {
    this.observers.push(observer)
  }
}

// 观察者
class Observer {
  constructor(name, subject) {
    this.name = name
    this.subject = subject
    this.subject.attach(this)
  }
  update() {
    console.log(`${this.name} update, state: ${this.subject.getState()}`)
  }
}

// 测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('02', s)

s.setState(12)

观察者模式总结其一

小结

  为解耦而生,为事件而生,符合开放封闭原则。

使用场景

  跨层级通信、事件绑定 vue 响应式 等

观察者模式总结其二

优点

  1、支持简单的广播通信,自动通知所有已经订阅过的对象
  
  2、目标对象与观察者之间的抽象耦合关系能单独扩展以及重用

  3、增加了灵活性

  4、观察者模式 所做的工作就是在 解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。

缺点

  过度使用会导致对象与对象之间的联系弱化,会导致程序难以跟踪维护和理解
posted @ 2023-03-28 15:44  caix-1987  阅读(24)  评论(0)    收藏  举报