This is the 11th day of my participation in Gwen Challenge

The observer pattern is essentially an object behavior pattern, while the publish/subscribe pattern is essentially an architectural pattern that emphasizes the role of components.

1. Observer mode

The Observer pattern is a design pattern in which an object (called a principal) maintains a list of objects against objects (observers), automatically notifying them of any changes to their state.

Intent: Define a one-to-many dependency between objects so that when an object’s state changes, all dependent objects are notified and automatically updated. Motivation: Splitting a system into a series of cooperating classes has a side effect: the need to maintain consistency between related objects. You don’t want to have classes tightly coupled for consistency, which reduces reusability.

“One or more interested in the subject of state observer, and by attaching their own interest to register the subject, when the subject interests of an observer changes, will send a notification message, call the update method in each topic observer, when no longer interested in the subject of state observer, they can easily separate themselves. “

Perhaps not all the important information can be gleaned from the above description. Let’s first look at an example from the Design Pattern book:

<! DOCTYPEhtml>
<html>
  <head>
    <title>The "Click the button" page</title>
    <meta charset="UTF-8">
  </head>
  <body>
    <button id="addNewObserver">Add New Observer checkbox</button>
    <input id="mainCheckbox" type="checkbox"/>
    <div id="observersContainer"></div>
    <script type="text/javascript" src='index.js'></script>
  </body>
</html>

Copy the code
/* * Subject * Creates three methods internally and maintains an ObserverList internally. * /

//contructor function
function Subject(){
  this.observers = new ObserverList();
}
 
//addObserver: calls the internally maintained add method of ObserverList
Subject.prototype.addObserver = function( observer ){
  this.observers.add( observer );
};
 
//removeObserver: Calls the removeat method of the internally maintained ObserverList
Subject.prototype.removeObserver = function( observer ){
  this.observers.removeAt( this.observers.indexOf( observer, 0)); };//notify: notify the observer and execute the update function. Update is a method that implements the interface and is a notification trigger method.
Subject.prototype.notify = function( context ){
  var observerCount = this.observers.count();
  for(var i=0; i < observerCount; i++){
    this.observers.get(i).update( context ); }};/* * ObserverList * Maintains an array internally, and four methods are used to manipulate the array. The relevant stuff here is subject again, because ObserverList is designed to decouple subject from observers. * /
function ObserverList(){
  this.observerList = [];
}
 
ObserverList.prototype.add = function( obj ){
  return this.observerList.push( obj );
};
 
ObserverList.prototype.count = function(){
  return this.observerList.length;
};
 
ObserverList.prototype.get = function( index ){
  if( index > -1 && index < this.observerList.length ){
    return this.observerList[ index ]; }}; ObserverList.prototype.indexOf =function( obj, startIndex ){
  var i = startIndex;
 
  while( i < this.observerList.length ){
    if( this.observerList[i] === obj ){
      return i;
    }
    i++;
  }
 
  return -1;
};
 
ObserverList.prototype.removeAt = function( index ){
  this.observerList.splice( index, 1 );
};

/* * The Observer * provides an update interface for principals that want to be notified of messages. * / 
function Observer(){
  this.update = function(){
    // ...
  };
}

// Extend an object with an extension
function extend( obj, extension ){
  for ( var key inextension ){ obj[key] = extension[key]; }}// References to our DOM elements
 
var controlCheckbox = document.getElementById( "mainCheckbox" ),
  addBtn = document.getElementById( "addNewObserver" ),
  container = document.getElementById( "observersContainer" );
 
// Concrete Subject
 
// Extend the controlling checkbox with the Subject class
extend( controlCheckbox, new Subject() );
 
// Clicking the checkbox will trigger notifications to its observers
controlCheckbox.onclick = function(){
  controlCheckbox.notify( controlCheckbox.checked );
};
 
addBtn.onclick = addNewObserver;
 
// Concrete Observer
function addNewObserver(){
  // Create a new checkbox to be added
  var check = document.createElement( "input" );
  check.type = "checkbox";
 
  // Extend the checkbox with the Observer class
  extend( check, new Observer() );
 
  // Override with custom update behaviour
  check.update = function( value ){
    this.checked = value;
  };
 
  // Add the new observer to our list of observers
  // for our main subject
  controlCheckbox.addObserver( check );
 
  // Append the item to the container
  container.appendChild( check );
}
Copy the code

Observer: Provides an update interface for objects that need to be notified of state changes of the Subject. ConcreteSubject: State ConcreteObserver: Store a reference to ConcreteSubject, implementing the update interface for observers to ensure that the state is consistent with the Subject

Then we will correspond the above parts to the example:

The specific operation process is as follows: a. Define the subject class and the observer class b. Instantiate the class into a concrete object, bind the method, and register the observer in the subject object C. Operation. The principal distributes messages to observers.



What kind of behavior do you see when you go over here?

The Observer pattern itself has defined the structure of the Observer and the topic, which is then inherited by the specific topic and Observer. This is why the above is an object behavior pattern. The relationship between the Subject and Observer is defined, which is a tightly coupled state.

Why does the observer do this? According to the name of the observer mode, its focus is on the object to be observed. The state of the observer needs to change with the notification of the subject, so it defines the close connection between the subject and the observer.


2. Publish/subscribe

The publish/subscribe pattern uses a topic/event channel between the object that wants to receive notification (the subscriber) and the object that initiates the event (the publisher). This event system allows code to define application-specific events that can pass custom parameters containing the values required by subscribers. The idea here is to avoid dependencies between users and publishers. It’s different here with the observer mode.

The emphasis is on subscribers subscribing to events, publishers publishing information, and what happens to subscribers once they receive information. But the problem with this place is that the Subject has become an actual part of the project, not a thing to regulate behavior. That’s why it was an architectural pattern in the first place.

var pubsub = {};
(function(myObject) {
    // Storage for topics that can be broadcast
    // or listened to
    var topics = {};
 
    // A topic identifier
    var subUid = -1;
 
    myObject.publish = function( topic, args ) {
 
        if ( !topics[topic] ) {
            return false;
        }
 
        var subscribers = topics[topic],
            len = subscribers ? subscribers.length : 0;
 
        while (len--) {
            subscribers[len].func( topic, args );
        }
 
        return this;
    };
 
    // Subscribe to events of interest
    // with a specific topic name and a
    // callback function, to be executed
    // when the topic/event is observed
    myObject.subscribe = function( topic, func ) {
 
        if(! topics[topic]) { topics[topic] = []; }var token = ( ++subUid ).toString();
        topics[topic].push({
            token: token,
            func: func
        });
        return token;
    };
 
    // Unsubscribe from a specific
    // topic, based on a tokenized reference
    // to the subscription
    myObject.unsubscribe = function( token ) {
        for ( var m in topics ) {
            if ( topics[m] ) {
                for ( var i = 0, j = topics[m].length; i < j; i++ ) {
                    if ( topics[m][i].token === token ) {
                        topics[m].splice( i, 1 );
                        returntoken; }}}}return this;
    };
}( pubsub ));

// A simple message logger that logs any topics and data received through our
// subscriber
var messageLogger = function ( topics, data ) {
    console.log( "Logging: " + topics + ":" + data );
};

// Subscribers listen for topics they have subscribed to and
// invoke a callback function (e.g messageLogger) once a new
// notification is broadcast on that topic
var subscription = pubsub.subscribe( "inbox/newMessage", messageLogger );
 
// Publishers are in charge of publishing topics or notifications of
// interest to the application. e.g:
 
pubsub.publish( "inbox/newMessage"."hello world!" );
 
// or
pubsub.publish( "inbox/newMessage"["test"."a"."b"."c"]);// or
pubsub.publish( "inbox/newMessage", {
  sender: "[email protected]".body: "Hey again!"
});
 
// We can also unsubscribe if we no longer wish for our subscribers
// to be notified
pubsub.unsubscribe( subscription );
 
// Once unsubscribed, this for example won't result in our
// messageLogger being executed as the subscriber is
// no longer listening
pubsub.publish( "inbox/newMessage"."Hello! are you still there?" );
Copy the code


3. The difference between the two

The contact observer pattern between topics and subscribers is a tightly coupled state, while the publish/subscribe pattern is a loosely coupled state.

Means of notifying subscribers

The observer pattern is implemented by traversing the observer through the topic itself and then calling the notification method of the subscriber. Publish/subscribe is notified through the event pipeline, and the subject of doing this is events, because at the time of executing a specific event, no one knows what the next method is? Because the subscribe/publish model maintains all subscriber events. In fact, it is as if one is teaching them to fish and the other is teaching them to fish.

The observer model tells us what to do next in the code, while the subscribe/publish model is like taking care of everything yourself.

Internal maintenance content

The observer mode maintains the observer, knowing which observers are paying attention. The subscribe/publish model skips this step and maintains the subscriber’s event mechanism directly, executing specific events well, who subscribes, whatever!

For example, the center is me, and I did two things. One was I bought a stock. The second is to subscribe to the newspaper. Both things happen every single day. But for me, what do I think?

The stock market opened, this day has been busy staring at the screen, afraid not to fall. In the case of the stock, the stock is the subject, and I am the subscriber, the relationship between us is very important to me, it is related to my money, can not be close. But the market is down today. I felt very depressed when I got home. After staying for a while, I remembered that today’s newspaper had not been delivered, so I made a phone call to ask what was going on. It was already here, picked up by my roommate. So I know when the paper arrives, and I don’t read it when I’m in a bad mood. As far as newspapers are concerned, all I care about is that today’s paper is printed and delivered.

reference

Addyosmani.com/resources/e… Blog.csdn.net/elibrace/ar… Segmentfault.com/a/119000001…