Observer

The observer pattern is perhaps the most used pattern in the JavaScript world. The pattern is used especially with modern single pages applications; it is a big part of the various libraries that provide Model View View-Model (MVVM) functionality. We'll explore those patterns in some detail in Chapter 7, Reactive Programming.

It is frequently useful to know when the value on an object has changed. In order to do so you could wrap up the property of interest with a getter and setter:

class GetterSetter {
  GetProperty() {
    return this._property;
  }
  SetProperty(value) {
    this._property = value;
  }
}

The setter function can now be augmented with a call to some other object which is interested in knowing that a value has changed:

SetProperty(value) {
  var temp = this._property;
  this._property = value;
  this._listener.Event(value, temp);
}

This setter will now notify the listener that a property change has occurred. In this case both the old and new value have been included. This is not necessary as the listener can be tasked with keeping track of the previous value.

The observer pattern generalizes and codifies this idea. Instead of having a single call to the listener, the observer pattern allows interested parties to subscribe to change notifications. Multiple subscribers can be seen in the following diagram:

Observer

Implementation

The court of Westeros is a place of great intrigue and trickery. Controlling who is on the throne and what moves they make is a complex game. Many of the players in the game of thrones employ numerous spies to discover what moves others are making. Frequently these spies are employed by more than one player and must report what they have found to all of the players.

The spy is a perfect place to employ the observer pattern. In our particular example, the spy being employed is the official doctor to the king and the players are very interested in how much painkiller is being prescribed to the ailing king. Knowing this can give a player advanced knowledge of when the king might die – a most useful piece of information.

The spy looks like the following:

class Spy {
  constructor() {
    this._partiesToNotify = [];
  }
  Subscribe(subscriber) {
    this._partiesToNotify.push(subscriber);
  }
  Unsubscribe(subscriber) {
    this._partiesToNotify.remove(subscriber);
  }
  SetPainKillers(painKillers) {
    this._painKillers = painKillers;
    for (var i = 0; i < this._partiesToNotify.length; i++) {
      this._partiesToNotify[i](painKillers);
    }
  }
}

In other languages, the subscriber usually has to comply with a certain interface and the observer will call only the interface method. This encumbrance doesn't exist with JavaScript and, in fact, we just give the Spy class a function. This means that there is no strict interface required for the subscriber. This is an example:

class Player {
  OnKingPainKillerChange(newPainKillerAmount) {
    //perform some action
  }
}

This can be used like so:

let s = new Spy();
let p = new Player();
s.Subscribe(p.OnKingPainKillerChange); //p is now a subscriber
s.SetPainKillers(12); //s will notify all subscribers

This provides a very simple and highly effective way of building observers. Having subscribers decouples the subscriber from the observable object.

The observer pattern can also be applied to methods as well as properties. In so doing you can provide hooks for additional behavior to happen. This is a common method of providing a plugin infrastructure for JavaScript libraries.

In browsers all the event listeners on various items in the DOM are implemented using the observer pattern. For instance, using the popular jQuery library, one can subscribe to all the click events on buttons on a page by doing the following:

$("body").on("click", "button", function(){/*do something*/})

Even in vanilla JavaScript the same pattern applies:

let buttons = document.getElementsByTagName("button");
for(let i =0; i< buttons.length; i++)
{
  buttons[i].onclick = function(){/*do something*/}
}

Clearly the observer pattern is very useful when dealing with JavaScript. There is no need to change the pattern in any significant fashion.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset