The Observer Pattern

This pattern implements a single object (the subject) that maintains a reference to a collection of objects (known as “observers”) and broadcasts notifications when a change to state occurs. When we don’t want to observe an object, we simply remove it from the collection of objects being observed. The observer pattern is similar to both the pub/sub implementation and the mediator pattern but still different in purpose & theory and worth mentioning. Study the example below for a good idea of what’s happening behind the scenes.

This article is part of a series called JavaScript Design Patterns.

Advantages

Disadvantages

Example

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
// build the Subject base class
var Subject = ( function( window, undefined ) {
 
function Subject() {
this._list = [];
}
 
// this method will handle adding observers to the internal list
Subject.prototype.observe = function observeObject( obj ) {
console.log( 'added new observer' );
this._list.push( obj );
};
Subject.prototype.unobserve = function unobserveObject( obj ) {
for( var i = 0, len = this._list.length; i < len; i++ ) {
if( this._list[ i ] === obj ) {
this._list.splice( i, 1 );
console.log( 'removed existing observer' );
return true;
}
}
return false;
};
Subject.prototype.notify = function notifyObservers() {
var args = Array.prototype.slice.call( arguments, 0 );
for( var i = 0, len = this._list.length; i < len; i++ ) {
this._list[ i ].update.apply( null, args );
}
};
 
return Subject;
 
} )( window );
 
// setup an object that fetchs stocks
function StockGrabber() {
var subject = new Subject();
this.addObserver = function addObserver( newObserver ) {
subject.observe( newObserver );
};
this.removeObserver = function removeObserver( deleteObserver ) {
subject.unobserve( deleteObserver );
};
this.fetchStocks = function fetchStocks() {
// fake fetching the stocks
var stocks = {
aapl : 167.00,
goog : 243.67,
msft : 99.34
};
// notify our observers of the stock change
subject.notify( stocks );
};
}
 
// define a couple of different observers
var StockUpdaterComponent = {
update : function() {
console.log( '"update" called on StockUpdater with: ', arguments );
}
};
var StockChartsComponent = {
update : function() {
console.log( '"update" called on StockCharts with: ', arguments );
}
};
 
// example usage
var stockApp = new StockGrabber();
stockApp.addObserver( StockUpdaterComponent );
stockApp.fetchStocks(); // console logs: "update" called on StockUpdater with...
stockApp.addObserver( StockChartsComponent );
stockApp.fetchStocks(); // console logs: "update" called on StockUpdater with... "update" called on StockCarts with...
stockApp.removeObserver( StockUpdaterComponent );
stockApp.fetchStocks(); // console logs: "update" called on StockCharts with...
stockApp.removeObserver( StockChartsComponent );
stockApp.fetchStocks(); // does nothing; no observers

In the example above, the Subject object becomes a base class from which we build an example stock tracking application. You can see that the StockGrabber object uses the Subject object internally to handle notifications to other components of the application such as the StockUpdaterComponent and the StockChartsComponent.

Additional Resources

https://www.youtube.com/watch?v=NZi5Ru4KVug
http://answers.oreilly.com/topic/2190-two-examples-of-the-observer-pattern-in-javascript/
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#observerpatternjavascript

Other Common JS Patterns

The Module Pattern
The Revealing Module Pattern
The Singleton Pattern
The Observer Pattern
The Mediator Pattern
The Prototype Pattern
The Facade Pattern
The Factory Pattern

No comments. You could be the first!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>