background

Definition of a design pattern: A concise and elegant solution to a specific problem in object-oriented software design.

Design pattern can not be directly used to complete the writing of code, but to describe how to solve problems in various situations, it is not a dead mechanism, it is a kind of idea, a form of code.

Each language has its own implementation for various design patterns, and some design patterns may not be applicable in some languages, such as factory patterns that are not applicable to JavaSctipt. Patterns should be used in the right place, and the right place is only known when we have a deep understanding of the intent of the pattern, combined with the actual scenario of the project.

Observer Pattern

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 behavior mode, which focuses on the communication between objects, while observer mode is the communication between the observer and the observed.

The observer model is also known as the “publish-subscribe” or “subscription-publish” model, in which the subscriber and the subscription target are linked, and the subscriber is notified individually when the subscription target changes. Let’s take newspaper and periodical subscription as an example. When you subscribe to a newspaper, a new newspaper will be delivered to you every day. As many people subscribe to the newspaper, the newspaper will issue many newspapers.

Pub-sub Pattern

There is no publish-subscribe pattern among the 24 basic design patterns. As explained above, it is just another name for the Observer pattern. But over time, it has grown so strong that it has become a new design pattern independent of the observer pattern.

In the current publish-subscribe model, the publisher’s messages are not sent directly to the subscriber, meaning that neither the publisher nor the subscriber is aware of each other’s existence. Between publishers and subscribers exists a third component, called a message broker or scheduling center or middleware, which maintains the link between publishers and subscribers, filters all incoming messages from publishers, and distributes them to their subscribers accordingly. For example, you follow A on Weibo, and many other people also follow A. When A releases an update, Weibo will push this update for you. A is the publisher and you are the subscriber. Weibo is the dispatching center. There is no direct communication between you and A.

What is the difference between the observer model and the publish-subscribe model?

Let’s first look at the implementation structure of the following two modes:

Observer mode: The Observer directly subscribes to the Subject, and when the Subject is activated, it fires events within the Observer.

Publish-subscribe model: Subscriber registers the event they want to Subscribe to the dispatch center. When Publisher publishes the event to the dispatch center, that is, when the event is triggered, The processing code registered with the dispatch center by the Fire Event subscriber.

case

Observer model

// There is a hunter guild where each hunter publishes and subscribes quests
// They all have a subscription list of who subscribes to them

// Define a hunter, including name, level, and subscription list
function Hunter(name, level) {
  this,name = name
  this.level = level
  this.list = []
}
Hunter.prototype.publish = function (money) {
  console.log(this,level + 'Hunter:' + this.name + 'Ask for help')
  this.list.forEach(function (callback) {
    callback && callback(money)
  })
}
Hunter.prototype.subscribe = function (target, callback) {
  console.log(this.level + 'Hunter:' + this.name + 'Subscribed:' + target.name)
  target.list.push(callback)
}

// The hunter guild has registered several hunters
var hunterZhang = new Hunter('Joe'.'diamond')
var hunterLi = new Hunter('bill'.'gold')
var hunterWang = new Hunter('Cathy'.'silver')
var hunterZhao = new Hunter('Daisy'.'bronze')

// Zhao liu is a lower rank and may need help, so Zhang SAN, Li Si and Wang Wu subscribe to Zhao Liu
hunterZhang.subscribe(hunterZhao, function (money) {
  console.log('Xiao Ming said:' + (money > 200 ? ' ' : 'I'm busy right now. I can't.') + 'Give a hand')
})
hunterLi.subscribe(hunterZhao, function () {
  console.log('Li Si says: Help')
})
hunterWang.subscribe(hunterZhao, function () {
  console.log('Wang Wu said: Give help')})// Zhao liu was in trouble and offered a reward for help
hunterZhao.publish(198)

// Hunters (observers) associate hunters (target objects) they are interested in, such as Zhao Vi, and automatically notify them when zhao Vi is in trouble.

Copy the code

Publish and subscribe

// Defines a hunter guild
// Main functions include topics (subscribe), publish (publish)
var HunterUnion = {
  type: 'hunt'.topics: Object.create(null),
  subscribe: function (topic, callback) {
    if (!this.topics[topic]) {
      this.topics[topic] = []
    }
    this.topics[topic].push(callback)
  },
  publish: function (topic, money) {
    if (!this.topics[topic]) {
      return
    }
    for(var cb of this.topics[topic]) {
      cb(money)
    }
  }
}

// Define a hunter, including name and rank
function Hunter(name, level) {
  this.name = name
  this.level = level
}
// Hunters can publish and subscribe quests in the hunter guild
Hunter.prototype.subscribe = function (task, fn) {
  console.log(this.level + 'Hunter:' + this.name + 'Subscribe to hunt:' + task + 'Task')
  HunterUnion.subscribe(task, fn)
}
Hunter.prototype.publish = function (task, money) {
  console.log(this.level + 'Hunter:' + this.name + 'Released the hunt:' + task + 'Task')
  HunterUnion.publish(task, money)
}

// The hunter's guild registered several hunters
let hunterZhang = new Hunter('Joe'.'diamond')
let hunterLi = new Hunter('bill'.'gold')
let hunterWang = new Hunter('Cathy'.'silver')
let hunterZhao = new Hunter('Daisy'.'bronze')

// Zhang SAN, Li Si and Wang Wu have subscribed to hunt Tiger respectively
hunterZhang.subscribe('tiger'.function(money){
  console.log('Zhang SAN said:' + (money > 200 ? ' ' : 'no') + 'Fetch task')
})
hunterLi.subscribe('tiger'.function(money){
  console.log('Li Si says: Pick up the task')
})
hunterWang.subscribe('tiger'.function(money){
  console.log('Wang Wu said: Pick up the task')})// Zhao liu subscribed to the task of hunting sheep
hunterZhao.subscribe('sheep'.function(money){
  console.log('Zhao Liu said: Pick up the task')})// Zhao Liu announces the task of hunting tiger
hunterZhao.publish('tiger'.198)

// Hunters publish (publisher) or subscribe (observer/subscriber) quests are linked through hunters guild (dispatch center), they do not communicate directly.
Copy the code

The biggest difference between the observer mode and the publish-subscribe mode is that the publish-subscribe mode has an event scheduling center.

The observer pattern is scheduled by specific targets, and each subscribed target needs to have observer processing, which can cause redundancy in the code.

In publish-subscribe mode, the scheduling process is unified, and subscribers and publishers do not interfere with each other, eliminating the dependence between publishers and subscribers. This allows for decoupling on the one hand and more fine-grained control on the other. For example, if a publisher publishes a lot of messages, but not all subscribers want to receive them, they can do some processing in the dispatch center, like permission control and so on. You can also do some throttling.

Is the observer model publish-subscribe?

In JavaScript Design Patterns and Development Practices, the key to identifying patterns is intent, not structure.

If patterns are distinguished by structure, the publish-subscribe pattern has one more dispatch center than the observer pattern, so publish-subscribe differs from the observer pattern.

If the intent to distinguish patterns, they all realized a one-to-many dependency between objects, when an object’s state is changed, all depend on the object will be notified, and automatically updates, so they are the same kind of pattern, the publish-subscribe pattern is on the basis of the observer pattern has been optimized to upgrade.

However, whether they are the same design pattern or not, they are implemented in different ways, and we should decide which one to choose based on the application scenario.