wangjing013 / blog

📝 记录

Home Page:https://wangjing013.github.io/blog/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

观察者模式

wangjing013 opened this issue · comments

它定义了对象间的一种一对多的关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

现实生活中发布订阅模式

在互联网时代网购是购物的重要途径之一。例如淘宝中某个商品性价比高的,通常它会出现卖断货情况,大家习惯性都会去问客服,它什么时候会有货?客服通常推荐去关注店铺的 补货通知

从上面例子中找出两个主要角色: 店铺客户。它分别对应着发布-订阅模式中的发布者订阅者

现在来捋一捋这关系,店铺与客户之间的关系是一种一对多的关系,当店铺收到仓库中有货源的时候(库存变化),就通知已经订阅了"补货通知"信息的这批人,这是不是跟观察查者模式的定义相吻合。

接下来通过具体实践来理解上面的定义。

在案例中来理解上面定义

首先发布者与订阅者在程序中体现就是两个类。

发布者应该具备什么样的功能? 取决于它要做的事。回顾下上面的案例店铺与客户是一对多的关系,通常要用集合对象来存储 ( list ) 对应的客户从而建立它们之间的关系。同样店铺具有“补货通知”功能( register ),相反它也应具备"取消"功能( unregister )。 当库存有货时就要进行通知功能( notify )。

订阅者应该具备什么样功能?对于客户而言,只要能够根据补货通知(update),完成一系列的购买事项即可。

基于上面的概念,抽象出 发布-订阅模式 对应的代码实现:

// 发布者
class Subject{
  constructor() {
    this.observerList = []
  }
  notifyObservers() {
    this.observerList.forEach((observer) => {
      observer.update()
    })
  }
  registerObserver(observer) {
    this.observerList.push(observer);
  }
  unregisterObserver(observer){
    this.observerList.forEach((item, i) => {
      if (item === observer) {
        this.observerList.splice(i, 1)
      }
    })
  }
}

// 订阅者
class Observer{
  update() {
    console.log("update");
  }
}

现在发布者和订阅者类已经定义好,在具体的业务场景中只要基于这两个类进行扩展就好。回到上面案例,现在通过代码来实现该场景:

// 店铺
class Store extends Subject {
  constructor() {
    super();
    // 库存
    this.list = [];
  }
  setState(list) {
    this.list = list;
    this.notifyObservers();
  }
}

// 客户
class Customer extends Observer {
  constructor() {
    super();
  }
  update() {
    console.log("有货啦");
    this.addCart();
  }

  addCart() {
    console.log("添加购物车成功");
  }
}

下面,执行对应的代码:

const store = new Store();
const customer0 = new Customer();
const customer1 = new Customer();

// 订阅
store.registerObserver(customer0);
store.registerObserver(customer1);
// 更新库存
store.setState([
  {
    goodName: "1"
  },
  {
    goodName: "2"
  }
]);

对应输出如下:

有货啦
添加购物车成功
有货啦
添加购物车成功

通过上面的案例,相信大家对观察者模式定义、使用有了初步的理解。