前端八股之设计模式-观察者模式&发布订阅模式

59 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

观察者模式

介绍:当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。 image-20210304210003822

特点:发布者(Publisher)与观察者(Observer)紧耦合,即发布者知道有多少人需要自己去通知

class Observer {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  do(): void {
    console.log(`${this.name},do...`);
  }
}

type action = "add" | "remove";
interface Types {
  type: String;
  target: Observer;
}
// 发布与订阅全部由发布者提供,并且发布者内部耦合了订阅者列表Observers
class Publisher {
  Observers: Array<Types> = [];
  subscribe(Observer: Observer, type: action) {
    this.Observers.push({ type, target: Observer });
  }

  notify(type: action) {
    this.Observers.map((item) => {
      if (item.type === type) {
        item.target.do();
      }
    });
  }
}
const obserA = new Observer("a");
const obserB = new Observer("b");
const obserC = new Observer("c");
const pub = new Publisher();
pub.subscribe(obserA, "add");
pub.subscribe(obserB, "add");
pub.notify("add");
pub.subscribe(obserC, "add");
pub.notify("add");

// a,do...
// b,do...
// a,do...
// b,do...
// c,do...

CodeSandbox

发布-订阅模式

这里我想通俗地讲一下发布订阅模式,拿B站作为例子

  • UP主:Publisher
  • 视频关注者(我们):Observer
  • B站平台:EventEmitter

我们关注了一个UP主之后,当UP主发送视频时,会把视频上传给B站,B站会做一系列操作,如审核(也就是过滤)之后,会把视频准确推送给所有订阅了该UP主的用户。

image-20210304214811992

特点:

  1. 发布者与订阅者松耦合,利用中间者代理实现这种模式。每次发布者发布讯息只需要和中间者说就行了,中间者还可以做一些过滤的操作或者其他更丰富的操作,最后通知相应订阅者即可。
class Publisher {
  EventEmitter: EventEmitter;
  constructor(EventEmitter: EventEmitter) {
    this.EventEmitter = EventEmitter;
  }
  notify(type: action) {
    this.EventEmitter.notify(type);
  }
}
class Observer {
  name: String;
  EventEmitter: EventEmitter;
  constructor(name: String, Emitter: EventEmitter) {
    this.name = name;
    this.EventEmitter = Emitter;
  }
  subscribe(type: action) {
    this.EventEmitter.subscribe(this, type);
  }
  do() {
    console.log(`${this.name}, do....`);
  }
}

type action = "add" | "remove";
interface Types {
  type: string;
  target: Observer;
}
class EventEmitter {
  Observers: Array<Types> = [];

  subscribe(Observer: Observer, type: action) {
    this.Observers.push({ type, target: Observer });
  }

  notify(type: action) {
    this.Observers.map((item) => {
      if (item.type === type) {
        item.target.do();
      }
    });
  }
}
const Emitter = new EventEmitter();
const pubA = new Publisher(Emitter);
const obserA = new Observer("a", Emitter);
const obserB = new Observer("b", Emitter);
const obserC = new Observer("c", Emitter);
obserA.subscribe("add");
obserB.subscribe("add");
obserB.subscribe("remove");
pubA.notify("add");
obserC.subscribe("add");
pubA.notify("add");
pubA.notify("remove");
// result
// a, do....
// b, do....
// a, do....
// b, do....
// c, do....
// b, do....

CodeSandbox

发布-订阅模式与观察者模式的区别

主要区别就是发布订阅者模式有中间代理。

那么为什么会需要这个中间代理呢?

这就好比软件工程,松耦合的代码是利于移植的,因此在发布订阅者模式中,如果我们想要替换发布者或者订阅者,就更加容易修改与移植。如若是观察者模式则需要修改整个结构。 除此之外,中间代理者还能做很多其他的事情,例如过滤或者增强。如若想再观察者模式中实现额外功能,显然放在发布者或者观察者一方都好像不是很合适。