Javascript Design Patterns

I recently spent time refreshing myself on some software design patterns. I was specifically interested in how they should be applied using Javascript.

Why learn Design Patterns?

A pattern is a reusable solution that can be applied to commonly occurring problems in software design. In addition, they have the following benefits:

  1. Patterns are proven solutions
  2. Patterns can be easily reused
  3. Patterns can be expressive

Note that I am borrowing heavily from a great FREE book by Addy Osmani: Learning Javascript Design Patterns. I definitely recommend you check it out!

Constructor Pattern (with Prototypes)

Object constructors are used to create specific types of objects - both preparing the object for use and accepting arguments which a constructor can use to set the values of member properties and methods when the object is first created.

In Javascript, we should add methods to the prototype chain so we only hold them in memory once.

1
2
3
4
5
6
7
8
9
10
11
function Dog( age, name ) {
this.age = age;
this.name = name;
}
Dog.prototype.toString = function () {
return this.name + " is " + this.age + " years old!";
};
var dog1 = new Dog(3, 'buddy');
dog1.toString(); //"buddy is 3 years old!""

Module Pattern

In JavaScript, the Module pattern is used to emulate the concept of classes in such a way that we’re able to include both public/private methods and variables inside a single object, thus shielding particular parts from the global scope.

This results in is a reduction in the likelihood of our function names conflicting with other functions defined in additional scripts on the page.

Here is a generalized template for using the Modular Pattern in practice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
myPrivateVar = 0;
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
myPublicVar: "foo",
myPublicFunction: function( bar ) {
myPrivateVar++;
myPrivateMethod( bar );
}
};
})();

The Revealing Module Pattern

Let’s take a look at a slightly tweaked version of the Module pattern - Christian Heilmann’s Revealing Module pattern.

The Revealing Module Pattern is an updated pattern where we simply define all of our functions and variables in the private scope and return an anonymous object with pointers to the private functionality we wished to reveal as public.

You may have seen this pattern used in Angular.JS Factories and Services.

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
var myRevealingModule = (function () {
var privateCounter = 0;
function privateFunction() {
privateCounter++;
}
function publicFunction() {
publicIncrement();
}
function publicIncrement() {
privateFunction();
}
function publicGetCount(){
return privateCounter;
}
// Reveal public pointers to private functions and properties
return {
start: publicFunction,
increment: publicIncrement,
count: publicGetCount
};
})();
myRevealingModule.start();

The Singleton Pattern

The Singleton pattern restricts instantiation of a class to a single object. In the event of an instance already existing, it simply returns a reference to that object.

In JavaScript, Singletons serve as a shared resource namespace which isolate implementation code from the global namespace so as to provide a single point of access for functions.

In practice, the Singleton pattern is useful when exactly one object is needed to coordinate others across a system.

We can implement a Singleton as follows:

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
var mySingleton = (function () {
// Instance stores a reference to the Singleton
var instance;
function init() {
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
var privateVariable = "Im also private";
var privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true

The Observer Pattern

The Observer is a design pattern where an object (known as a subject) maintains a list of objects depending on it (observers), automatically notifying them of any changes to state.

Motivation behind using the Observer pattern is where we need to maintain consistency between related objects without making classes tightly coupled. For example, when an object needs to be able to notify other objects without making assumptions regarding those objects.

Here is a class to handle a list of observers:

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
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 );
};

Here is how you would turn a class into a observer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Subject(){
this.observers = new ObserverList();
}
Subject.prototype.addObserver = function( observer ){
this.observers.add( observer );
};
Subject.prototype.removeObserver = function( observer ){
this.observers.removeAt( this.observers.indexOf( observer, 0 ) );
};
Subject.prototype.notify = function( context ){
var observerCount = this.observers.count();
for(var i=0; i < observerCount; i++){
this.observers.get(i).update( context );
}
};

In Progress -> more Design Patterns coming soon!