I. Observer model

The observer pattern defines a one-to-many dependency between objects. When an object’s state changes, all dependent objects are notified and updated automatically

Observer mode belongs to behavioral mode, which focuses on the communication between objects, while observer mode is the communication between the observer and the observed

For example, in daily life, we can use newspaper and periodical subscription to illustrate vividly. When you subscribe to a newspaper, a new newspaper will be delivered to you every day. The number of people subscribing to the newspaper will be the number of newspapers distributed by the newspaper

Newspapers and their subscribers form a one-to-many dependency

The implementation code is as follows:

Observed model

class Subject {
  constructor() {
    this.observerList = [];
  }
  addObserver(observer) {
    this.observerList.push(observer);
  }
  removeObserver(observer) {
    const index = this.observerList.findIndex(o= > o.name === observer.name);
    this.observerList.splice(index, 1);
  }
  notifyObservers(message) {
    const observers = this.observeList;
    observers.forEach(observer= >observer.notified(message)); }}Copy the code

Observer:

class Observer {

  constructor(name, subject) {
    this.name = name;
    if (subject) {
      subject.addObserver(this); }}notified(message) {
    console.log(this.name, 'got message', message); }}Copy the code

Use the following code:

const subject = new Subject();
const observerA = new Observer('observerA', subject);
const observerB = new Observer('observerB');
subject.addObserver(observerB);
subject.notifyObservers('Hello from subject');
subject.removeObserver(observerA);
subject.notifyObservers('Hello again');
Copy the code

In the above code, the observer actively applies to be added to the observed list, and the observed actively adds the observer to the list

Publish and subscribe mode

Publish-subscribe is a messaging paradigm in which a sender of a message (called a publisher) does not directly send the message to a particular recipient (called a subscriber). Instead, they divide published messages into different categories without knowing which subscribers, if any, might exist

Similarly, subscribers can express interest in one or more categories and receive only messages of interest without knowing which publishers exist

The implementation code is as follows:

class PubSub {
  constructor() {
    this.messages = {};
    this.listeners = {};
  }
  // Add publishers
  publish(type, content) {
    const existContent = this.messages[type];
    if(! existContent) {this.messages[type] = [];
    }
    this.messages[type].push(content);
  }
  // Add subscribers
  subscribe(type, cb) {
    const existListener = this.listeners[type];
    if(! existListener) {this.listeners[type] = [];
    }
    this.listeners[type].push(cb);
  }
  / / notice
  notify(type) {
    const messages = this.messages[type];
    const subscribers = this.listeners[type] || [];
    subscribers.forEach((cb, index) = >cb(messages[index])); }}Copy the code

The publisher code is as follows:

class Publisher {
  constructor(name, context) {
    this.name = name;
    this.context = context;
  }
  publish(type, content) {
    this.context.publish(type, content); }}Copy the code

The subscriber code is as follows:

class Subscriber {
  constructor(name, context) {
    this.name = name;
    this.context = context;
  }
  subscribe(type, cb) {
    this.context.subscribe(type, cb); }}Copy the code

Use the following code:

const TYPE_A = 'music';
const TYPE_B = 'movie';
const TYPE_C = 'novel';

const pubsub = new PubSub();

const publisherA = new Publisher('publisherA', pubsub);
publisherA.publish(TYPE_A, 'we are young');
publisherA.publish(TYPE_B, 'the silicon valley');
const publisherB = new Publisher('publisherB', pubsub);
publisherB.publish(TYPE_A, 'stronger');
const publisherC = new Publisher('publisherC', pubsub);
publisherC.publish(TYPE_C, 'a brief history of time');

const subscriberA = new Subscriber('subscriberA', pubsub);
subscriberA.subscribe(TYPE_A, res= > {
  console.log('subscriberA received', res)
});
const subscriberB = new Subscriber('subscriberB', pubsub);
subscriberB.subscribe(TYPE_C, res= > {
  console.log('subscriberB received', res)
});
const subscriberC = new Subscriber('subscriberC', pubsub);
subscriberC.subscribe(TYPE_B, res= > {
  console.log('subscriberC received', res)
});

pubsub.notify(TYPE_A);
pubsub.notify(TYPE_B);
pubsub.notify(TYPE_C);
Copy the code

For the code mentioned above, the publisher and subscriber need to be associated through the publishing and subscription center. The publishing action of the publisher and the subscription action of the subscriber are independent of each other, and there is no need to pay attention to each other. The message is distributed by the publishing and subscription center

Third, the difference between

The two design modes have the same idea. Take life as an example:

  • Observer mode: a company sends moon cakes and zongzi to its employees, which is sent by the administrative department of the company. This matter is not suitable to be handed over to a third party, because “the company” and “employees” are a whole
  • Publish-subscribe model: a company needs to send various kinds of express to other people. Because the company and other people are independent, the only bridge is the express, so this matter is suitable for the third-party express company to solve

In the above process, if the company manages the delivery of express by itself, the company will become an express company with complicated and difficult business to manage, which will affect the company’s main business. Therefore, what mode should be used and what conditions should be considered to be coupled

The differences between the two are shown below:

  • In the observer mode, the observer is aware of the Subject, and the Subject keeps a record of the observer. However, in the publish-subscribe model, publishers and subscribers are unaware of each other’s existence. They communicate only through the message broker.
  • In the publish-subscribe pattern, components are loosely coupled, as opposed to the observer pattern.
  • The observer pattern is synchronous most of the time, such that when an event is triggered, the Subject calls the observer’s methods. The publish-subscribe pattern is asynchronous most of the time (using message queues)

The following article is from a daily JS question, written by Grey