Observer vs. publish subscribe

Publish-subscribe Pattern

“Observer Pattern”

The Observer pattern and the publish-subscribe pattern are not strictly the same, and the publish-subscribe pattern is an extended implementation of the Observer pattern

The difference is that the publish-subscribe model has an extra channel, as shown in the figure below:


For example, you (publisher) are a very popular person, you have a lot of friends (observers), they all follow you and tell you in advance, “Remember me when you get married” (subscribe).

So you write down their contact information in your address book (cached list), and then when you want to get married, you send out the invitations one by one (trigger callback), and you can specify the time and place of the wedding on the invitations (upload reference to callback).

Friends can attend according to the time and place when they receive the invitation (accept the method of parameter implementation)

Code implementation

Start by defining a topic class

class Subject{
   constructor(){
    this.observers=[]
  }
  addObserver(observer){}
  
  removeObserve(){}
  
  notify(){}}Copy the code

Define an observer class

class Observer{
  update(){}
  
  subscribeTo(subject){
    subject.addObserver(this)}}Copy the code

Once the general framework is in place, fill in the contents of each method

class Subject{
  constructor(){
    this.observers=[]
  }
  addObserver(observer){
    this.observers.push(observer)
  }
  
  removeObserve(observer){
    let index=this.observers.indexOf(observer)
    if(index>-1) {this.observer.splice(index,1)}}notify(){
    this.observers.forEach(observer= >{
      observer.update()
    })
  }
}

class Observer{
  update(){}
  
  subscribeTo(subject){
    subject.addObserver(this)}}Copy the code
/ / test
let subject=new Subject()
let observer1=new Observer()
let observer2=new Observer()
let observer3=new Observer()
observer1.update=function(){
  console.log('1 update')
}
observer2.update=function(){
  console.log('2 update')
}
observer3.update=function(){
  console.log('3 update')
}


observer1.subscribeTo(subject)
observer2.subscribeTo(subject)
observer3.subscribeTo(subject)
subject.notify()1 update / 2 update / 3 update
Copy the code

Code link

The observer pattern is applied to EventBus

class EventBus{
  constructor(){
    this.map=[]
  }
  
  on(type,handler){
    this.map[type]=(this.map[type] || []).concat(handler)
  }
  
  off(type,handler){
    if(this.map[type]){
      if(! handler){delete this.map[type]
      }else{
        let index=this.map[type].indexOf(handler)
        this.map[type].splice(index,1)}}}fire(type,data){
      this.map[type] && this.map[type].forEach(handler= >handler(data))
  }

}  

const eventBus=new EventBus()
eventBus.on('click'.data= >{
  console.log(data)
}
eventBus.fire('click', {a:1.b:2})
Copy the code

In the publish-subscribe model, there is an additional publishing channel between publisher and subscriber. Receiving events from publishers on the one hand and publishing them to subscribers on the other; Subscribers need to subscribe to events from the event channel

/ / subscriber
class Subscriber{
    update(){}
    //update(event){}
    subscribeTo(channel){
       channel.addSubscriber(this)}}/ / publisher
class Publisher{
    notify(channel){
      channel.publish()
      //channel.publish(event)}}// Middle channel
class Channel{
     constructor(){
       this.subscribers=[]
     }

     addSubscriber(subscriber){
       this.subscribers.push(subscriber)
     }

     removeSubscriber(subscriber){
       let index=this.observers.indexOf(subscriber)
       if(index>-1) {this.subscribers.splice(index,1)}}publish(){
     //publish(event){
         this.subscribers.forEach(subscriber= >{
         subscriber.update()
         //subscriber.update(event)}}})Copy the code
// Test, new a Chanel object, publisher object, and three subscriber objects
let channel=new Channel()
let publisher=new Publisher()

let subscriber1=new Subscriber()
let subscriber2=new Subscriber()
let subscriber3=new Subscriber()


subscriber1.update=function(){
  console.log('1 update')
}
subscriber2.update=function(){
  console.log('2 update')
}
subscriber3.update=function(){
  console.log('3 update')}// Subscribers subscribe to the middle channel
subscriber1.subscribeTo(channel)
subscriber2.subscribeTo(channel)
subscriber3.subscribeTo(channel)

// Publishers only publish events to the middle channel
publisher.notify(channel)


Copy the code

Code link

All the above are publishers pushing data to subscribers, and can also be realized to actively pull data for subscribers.


Vue responsive principle (II) Observer, Dep, Watcher


reference

  • Observer vs Pub-Sub pattern
  • Handwritten publish and subscribe model