Design patterns are scary, though they gets lighter when you see the code. Most of us write Modular pattern but rarely realize it. Let’s look at the basic idea behind the popular patterns and understand through code.

Creational pattern

Idea: creating new things

var obj = {};

// Other ways
// var obj = Object.create(null);
// var obj = new Object();
// var obj = Object();

obj.property1 = 'Hello';
obj['property2'] = 'World';
Object.defineProperty(obj, 'property3', {
    value: '!',
    writable: true,         // If not mentioned, all three values are set as false
    enumerable: true,
    configurable: true
});

Object.defineProperties(obj, {
    'property4': {
        value: 'one more ',
        writable: true,         // If not mentioned, all three values are set as false
        enumerable: true,
        configurable: true
    }, 
    'property5': {
        value: 'time',
        writable: true,         // If not mentioned, all three values are set as false
        enumerable: true,
        configurable: true
    }   
});

obj.reveal = function() {

    for(var prop in this) {

        if(this.hasOwnProperty(prop)) {
            console.log(this[prop]);
        }
    }
};

obj.reveal();

Constructor Pattern

Idea: creating specific type of objects

function TwitterAccount() {

    function someEncryption() {
        console.log('Just made your password more secure.');
        return 'secure password';
    }

    this.username = username;
    this.password = someEncryption(password);
    this.image = 'default Avatar';
    console.log('Your new account has been created.');
} 

TwitterAccount.addCity = function(city) {
    this.city = city;
    console.log('Your info has been saved.');
};

TwitterAccount.addImage = function(image) {
    this.image = image;
    console.log('Your info has been saved.');
};

var inLoveWithHashTags = new TwitterAccount('HashYo', 'HashLover');
inLoveWithHashTags.addCity('HashTown');
inLoveWithHashTags.addImage('HashPng');

Singelton Pattern

Idea: provides a single instance to interact with for everyone

var Singelton = (function() {

    var instance;
    var Project = function() {
        this.baseUrl = '/';
        this.VERSION = '1.2';
        this.currentUrl = '/homepage';
    };

    Project.prototype.setUrl = function(pagename) { 
        this.currentUrl = baseUrl + pagename;
    };

    return {
        // returns same instance of `Project` no 
        // matter how many times called
        getInstance: function() {
            instance = instance || (new Project());
            return instance;
        }
    };
})();

var instance1 = Singelton.getInstance();
var instance2 = Singelton.getInstance();

instance1 === instance2;    //true

Module Pattern

Idea: an exposed public api which gives access to a common hidden code

var AnalyticsModule = (function() {

    var viewCounter = 0;
    return {
        increaseViews: function() {
            viewCounter++;
        },
        getTotalViews: function() {
            return viewCounter;
        },
        resetViews: function() {
            viewCounter = 0;
        }
    }
})();

Observer Pattern aka Publish/Subscribe

Idea: one object watches the other loose coupling

/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
 * http://benalman.com/
 * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
 
(function($) {
 
  var o = $({});
 
  $.subscribe = function() {
    o.on.apply(o, arguments);
  };
 
  $.unsubscribe = function() {
    o.off.apply(o, arguments);
  };
 
  $.publish = function() {
    o.trigger.apply(o, arguments);
  };
 
}(jQuery));

// basic pubsub without jQuery
var pubsub = (function() {

  var pubsubModel = {};

  return {
    subscribe: function(event, handler) {

      pubsubModel[event] = pubsubModel[event] || [];
      pubsubModel[event].push(handler);

    },
    unsubscribe: function(event, handler) {

      var handlerString = handler.toString();
      pubsubModel[event] = pubsubModel[event].filter(function(h) {
        
        return h.toString() !== handlerString;
      });
    },
    publish: function(event, data) {

      pubsubModel[event].forEach(function(func) {
        func(data);
      });
    }
  };

})();

Facade Pattern

Idea: to show a different face, conceal the reality

var addMyEvent = function( element, event, handler ){
  
  if(element.addEventListener){
  
    element.addEventListener( event, handler, false );
  
  }else if(element.attachEvent){
  
    element.attachEvent( 'on'+ event, handler );
  
  } else{
  
    element['on' + event] = handler;
  
  }

};

Factory Pattern

Idea: create mutiple type of objects through same interface

function Elephant() {
  this.ear = 2;
  this.career = 'zoo';
  this.trunk = 'only one'
}
 
function Zebra() {
  this.skin = 'stripes';
  this.lookalike = 'donkey';
}

function Pig() {
  this.loves = 'shit';
  this.motto = 'eat & sleep';
} 

function AnimalFactory() {}

AnimalFactory.prototype.giveMe = function (option) {
  
  var parentClass = null;
  
  if( options.animType === 'elephant' ) {

    parentClass = Elephant;

  } else if( options.animType === 'zebra' ) {

    parentClass = Zebra;

  } else if( options.animType === 'pig' ) {

    parentClass = Pig;

  }
  
  if( parentClass === null ) {

    return false;

  }
  
  return new parentClass( options );

}
 
// example usage
var zoo = new AnimalFactory();

var pig = zoo.giveMe({ animType: 'pig' });

var zebra = zoo.giveMe({ animType: 'zebra' });
 
console.log( pig instanceof Pig );
console.log( zebra instanceof Zebra );

Decorator Pattern

Idea: when making subclass doesn’t make sense

// Example 1.

function Vehicle( vehicleType ){

    this.vehicleType = vehicleType || 'car';
    this.model = 'default';
    this.license = '00000-000';
}


// This is how a basic instance looks like
var plane = new Vehicle('plane');   

var truck = new vehicle('truck');

// Instead of making a seperate `truck` subclass of vehicle
// better we will decorate it.
// Let the decoration begin
truck.setModel = function( modelName ){     
    this.model = modelName;
}

truck.setColor = function( color ){
    this.color = color;
}

truck.setModel('CAT');
truck.setColor('blue');

// Here 'Vehicle' works as before
var car = new vehicle('car');

// Example 2.
// What we're going to decorate
function MacBook() {
    this.cost = function () { return 997; };
    this.screenSize = function () { return 13.3; };
}

// Decorator 1
function Memory( macbook ) {
    var v = macbook.cost();
    macbook.cost = function() {
        return v + 75;
    }
}

// Decorator 2
function Engraving( macbook ){
    var v = macbook.cost();
    macbook.cost = function(){
        return v + 200;
    };
}

// Decorator 3
function Insurance( macbook ){
    var v = macbook.cost();
    macbook.cost = function(){
        return v + 250;
    };
}

var macAir = new MacBook();

Memory(macAir);     // decorating once
Engraving(macAir);  // decorating again
Insurance(macAir);  // how many times i want