JavaScript Design Patterns




In today’s blog, we will look at a number of JavaScript design patterns and implementation of those patterns. There is not an ideal pattern or set of patterns to use in the web application we work on. Each script and web application is its own needs and we need to think about where  a pattern can offer real value to an implementation. For example, some projects may benefit from the decoupling benefits offered by the Observer pattern whilst others may simply be too small for decoupling to be a concern at all.
So a firm grasp of design patterns means to identify the problems and integrate the design patterns in the application to solve those problems more easily.

We will discuss the following design patterns:
  • Constructor Pattern
  • Module Pattern
  • Revealing Module Pattern
  • Singleton Pattern
  • Observer Pattern
  • Mediator Pattern
  • Prototype Pattern
  • Command Pattern
  • Facade Pattern
  • Factory Pattern
  • Mixin Pattern
  • Decorator Pattern
  • Flyweight Pattern

 

The Constructor Pattern

In object-oriented programming languages, a constructor is a special method used to initialize a newly created object once memory has been allocated for it. In JavaScript, as almost everything is an object, we're most often interested in object constructors.
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.
There are three basic way to create new object in JavaScript.
var myObject = {};
var myObject = Object.create( null );
var myObject = new Object();
There are then four ways in which keys and values can then be assigned to an object:
// 1. Dot syntax
myObject.someKey = "Hello World";
var key = myObject.someKey;

// 2. Square bracket syntax
myObject["someKey"] = "Hello World";
var key = newObject["myKey"];
// 3. Object.defineProperty
anOldObject.defineProperty( myObject, "someKey", {
                value: "for more control of the property's behavior",
                writable: true,
                enumerable: true,
                configurable: true
            });


// If the above feels a little difficult to read, a short-hand could
// be written as follows:

var defineProp = function ( obj, key, value ){
config.value = value;
Object.defineProperty( obj, key, config );
};

// To use, we then create a new empty "person" object
var person = Object.create( null );

// Populate the object with properties
defineProp( person, "car",  "Delorean" );
defineProp( person, "dateOfBirth", "1981" );
defineProp( person, "hasBeard", false );
// 4. Object.defineProperties
Set properties
Object.defineProperties( newObject, {
"someKey": {
            value: "Hello World",
            writable: true
            },

"anotherKey": {
                        value: "Foo bar",
                        writable: false
            }

});

As we all know, JavaScript doesn't support the concept of classes but it does support special constructor functions that work with objects.

function Car( model, year, miles ) {

            this.model = model;
            this.year = year;
            this.miles = miles;

            this.toString = function () {
            return this.model + " has done " + this.miles + " miles";
            };
}
           
// We can create new instances of the car
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );

console.log( civic.toString() );
console.log( mondeo.toString() );


The Module Pattern

Modules are an integral piece of any robust application's architecture and typically help in keeping the units of code for a project both cleanly separated and organized.
In JavaScript, there are several options for implementing modules. These include:
  • The Module pattern
  • Object literal notation
  • AMD modules
  • CommonJS modules
  • ECMAScript Harmony modules
In JavaScript, the Module pattern is used to further emulate the concept of classes in such a way that we're able to include methods and variables inside a single object, thus protecting particular parts from the global scope.

The Module pattern

The Module pattern encapsulates "privacy", state and organization using closures. It provides a way of wrapping a mix of public and private methods and variables, protecting pieces from leaking into the global scope and accidentally colliding with another developer's interface. With this pattern, only a public API is returned, keeping everything else within the closure private.
It should be noted that there isn't really an explicitly true sense of "privacy" inside JavaScript because unlike some traditional languages, it doesn't have access modifiers. Variables can't technically be declared as being public nor private and so we use function scope to simulate this concept. Within the Module pattern, variables or methods declared are only available inside the module itself thanks to closure. Variables or methods defined within the returning object however are available to everyone.
This gives us a clean solution for shielding logic doing the heavy lifting whilst only exposing an interface we wish other parts of our application to use. The pattern is quite similar to an immediately-invoked functional expression (IIFE) except that an object is returned rather than a function.
Following is an implementation of the Module pattern by creating a module which is self-contained.
var myCounterModule = (function () {
             
              var counter = 0;
             
              return {
             
                incrementCounter: function () {
                  return counter++;
                },
             
                resetCounter: function () {
                  console.log( "counter value prior to reset: " + counter );
                  counter = 0;
                }
              };
             
})();
             

             
// Increment our counter
myCounterModule.incrementCounter();
             
// Check the counter value and reset
myCounterModule.resetCounter();

In the above example, The counter variable is actually fully protected from our global scope so it acts just like a private variable.

Now look at a more comprehensive example of Module pattern.

var myNamespace = (function () {
             
              var myPrivateVar, myPrivateMethod;
             
              // A private counter variable
              myPrivateVar = 0;
             
              // A private function which logs any arguments
              myPrivateMethod = function( foo ) {
                  console.log( foo );
              };
             
              return {
             
                // A public variable
                myPublicVar: "foo",
             
                // A public function utilizing privates
                myPublicFunction: function( bar ) {
             
                  // Increment our private counter
                  myPrivateVar++;
             
                  // Call our private method using bar
                  myPrivateMethod( bar );
             
                }
              };
             
})();

 

Object Literals


In object literal notation, an object is described as a set of comma-separated name/value pairs enclosed in curly braces ({}). Names inside the object may be either strings or identifiers that are followed by a colon. There should be no comma used after the final name/value pair in the object as this may result in errors.

var myObjectLiteral = {
             
            variableKey: variableValue,

            functionKey: function () {
            // To do something
            };
};

Object literals don't require instantiation using the new operator.
Below we can see a more complete example of a module defined using object literal notation:

var myModule = {
             
              myProperty: "someValue",
             
              // object literals can contain properties and methods.
              // e.g we can define a further object for module configuration:
              myConfig: {
                useCaching: true,
                language: "en"
              },
             
              // a very basic method
              myMethod: function () {
                console.log( "My very basic method…!!!" );
              },
             
              // output a value based on the current configuration
              myMethod2: function () {
                console.log( "Caching is:" + ( this.myConfig.useCaching ) ? "enabled" : "disabled" );
              },
             
              // override the current configuration
              myMethod3: function( newConfig ) {
             
                if ( typeof newConfig === "object" ) {
                  this.myConfig = newConfig;
                  console.log( this.myConfig.language );
                }
             }
};
             
            // Outputs: My very basic method…!!!
            myModule.myMethod();
             
            // Outputs: enabled
            myModule.myMethod2();
             
            // Outputs: fr
            myModule.myMethod3({
              language: "fr",
              useCaching: false
            });


Using object literals can assist in encapsulating and organizing our code

Pros and Cons

Pros

Code managability is easy the application using module pattern.
This gives us a clean solution for shielding logic doing the heavy lifting whilst only exposing an interface we wish other parts of our application to use.
In many cases the Module pattern is still quite useful and when used correctly, certainly has the potential to improve the structure of our application.

Cons

The disadvantages of the Module pattern are that as we access both public and private members differently, when we wish to change visibility, we actually have to make changes to each place the member was used.
We also can't access private members in methods that are added to the object at a later point.
Other disadvantages include the inability to create automated unit tests for private members and additional complexity when bugs require hot fixes


We today's blog, we looked at JavaScript design patterns. In this series of JavaScript design patterns, we will see other design patterns in up-coming blogs.

Happy Programming...!!!

Comments

Popular posts from this blog

Data Bound Controls in ASP.Net - Part 4 (FormView and DetailsView controls)

JavaScript - ES2015 (aka ES6)

The Clickjacking attack and X-Frame-Options