interface

/*                                                                                  The idea
behind this approach is simple: if an object contains methods that are named the same as the
methods defined in your interface, it implements that interface. Using a helper function, you
can ensure that the required methods are there:
*/
var Interface = function(name, methods) {
    if(arguments.length != 2) {
        throw new Error("Interface constructor called with " + arguments.length +
          "arguments, but expected exactly 2.");
    }
    this.name = name;
    this.methods = [];
    for(var i = 0, len = methods.length; i < len; i++) {
        if(typeof methods[i] !== 'string') {
            throw new Error("Interface constructor expects method names to be "
              + "passed in as a string.");
        }
        this.methods.push(methods[i]);
    }
};
// Static class method.
Interface.ensureImplements = function(object) {
    if(arguments.length < 2) {
        throw new Error("Function Interface.ensureImplements called with " +
          arguments.length + "arguments, but expected at least 2.");
    }
    for(var i = 1, len = arguments.length; i < len; i++) {
        var interface = arguments[i];
        if(interface.constructor !== Interface) {
            throw new Error("Function Interface.ensureImplements expects arguments"
              + "two and above to be instances of Interface.");
        }
        for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j++) {
            var method = interface.methods[j];
            if(!object[method] || typeof object[method] !== 'function') {
                throw new Error("Function Interface.ensureImplements: object "
                  + "does not implement the " + interface.name
                  + " interface. Method " + method + " was not found.");
            }
        }
    }
};
 
/*
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
 
var CompositeForm = function(id, method, action) {
    ...
};
...
function addForm(formInstance) {
     Interface.ensureImplements(formInstance, Composite, FormItem);
     //Interface.ensureImplements provides a strict check. If a problem is found, an error will be
     //thrown, which can either be caught and handled or allowed to halt execution. Either way, the
     //programmer will know immediately that there is a problem and where to go to fix it.
}
*/

Constants

Constants cant be modified at runtime you can emulate constants by creating a private variable with an accessor but no mutator.

 
CONST.getUPPER_BOUND();
 
var CONST = (function() {
        // Constants (created as private static attributes)
        var UPPER_BOUND = 100;
        // Privileged static method.
        this.getUPPER_BOUND() {
            return UPPER_BOUND;
        }
 
        // Return the constructor.
        return this;
})();
 
// or you can create a single generic accessor method:
var CONST = (function() {
        // Private static attributes.
        var constants = {
            UPPER_BOUND: 100,
            LOWER_BOUND: -100
        }
        // Privileged static method.
        this.get(name) {
            return constants[name];
        }
        return this;
})();
 
//use:
CONST.get('UPPER_BOUND');

Mixin

// Mixin class
var Serializable = function() {};
Serializable.prototype = {
    serialize: function() {
        var output = [];
        for(key in this) {
            output.push(key + ': ' + this[key]);
        }
        return output.join(', ');
    }
};
mixin(Author, Serilizable);
var author = new Author('Ross Harmes', ['JavaScript Design Patterns']);
var serializedString = author.serialize();
 
/*
copy all funxctions in Serializable
augment(Author, Serializable);
 
param a_functions copy only given methods names
augment(Author, Serializable, 'serialize');
*/
function mixin(receivingClass, givingClass /*, a_functions */ ) {
    if(arguments[2]) {
        // Only give certain methods.
        var a_functions = arguments[2];
        for(var i = 0, i< arguments.length; i++) {
            var f = arguments[i];
            receivingClass.prototype[f] = givingClass.prototype[f];
        }
    } else { // Give all methods.
        for(methodName in givingClass.prototype) {
            if( !receivingClass.prototype[methodName] ) {
                receivingClass.prototype[methodName] = givingClass.prototype[methodName];
            }
        }
    }
}

Singleton

// Basic Singleton
var Singleton = {
    attribute1: true,
    attribute2: 10,
    method1: function() {
    },
    method2: function(arg) {
    }
};
 
Singleton.attribute1 = false;
var total = Singleton.attribute2 + 5;
var result = Singleton.method1();

By providing a single point of access, the singleton pattern has the potential to tightly couple modules together. This is the main complaint leveraged at this pattern, and it is a valid one. There are times when it is better to create an instantiable class, even if it is only ever instanti- ated once. It also makes your code harder to unit test because it has the potential to tightly couple classes together.

// General skeleton for a lazy loading singleton
GiantCorp.Logger = (function() {
    var uniqueInstance; // Private attribute that holds the single instance.
    function constructor() {
        // All of the normal singleton code goes here.
    }
    return {
        getInstance: function() {
            if(!uniqueInstance) { // Instantiate only if the instance doesn't exist.
                uniqueInstance = constructor();
            }
            return uniqueInstance;
        },
        write: function(){}
    }
})();
 
var s = GiantCorp.Logger.getInstance().write('ok!');

Namespacing

var GiantCorp = window.GiantCorp || {};
GiantCorp.Common = {
   // A singleton with common methods used by all objects and modules.
};
GiantCorp.ErrorCodes = {
   // An object literal used to store data.
};
 
/* Generic Page Object. */
GiantCorp.PageName = {
    // Page constants.
    CONSTANT_1: true,
    CONSTANT_2: 10,
    // Page methods.
    method1: function() { }
    // Initialization method.
    init: function() {
    }
};
// Invoke the initialization method after the page loads.
addLoadEvent(GiantCorp.PageName.init);

Factory

Using a factory you can decouple objects. instead of the new keyword and a concrete class allows you to centralize all of the instantiation code in one location. This makes it much easier to swap classes, or to assign classes dynamically at run-time. Factory methods shouldn't be used when there isn't any chance of swapping out a different class or when you don't need to select interchangeable classes at run-time.

// BicycleShop class
var BicycleShop = function() {};
BicycleShop.prototype = {
    sellBicycle: function(model) {
        var bicycle;
        switch(model) {
        case 'The Speedster':
            bicycle = new Speedster();
            break;
        case 'The Lowrider':
            bicycle = new Lowrider();
            break;
        case 'The Comfort Cruiser':
        default:
            bicycle = new ComfortCruiser();
        }
        Interface.ensureImplements(bicycle, Bicycle);
        bicycle.assemble();
        bicycle.wash();
        return bicycle;
    }
};

Each time a browser dependent method is called (es. XHR), all of the browser sniffing code must be run again. This can be very inefficient if the method is called often. A more efficient way is to assign the browser-specific code only once, when the script loads. That way, once the initialization is complete, each browser only executes the code specific to its implementation of JavaScript.

// SimpleXhrFactory singleton
var SimpleXhrFactory = (function() {
    // The three branches.
    var standard = {
        createXhrObject: function() {
            return new XMLHttpRequest();
        }
    };
    var activeXNew = {
        createXhrObject: function() {
            return new ActiveXObject('Msxml2.XMLHTTP');
        }
    };
    var activeXOld = {
        createXhrObject: function() {
            return new ActiveXObject('Microsoft.XMLHTTP');
        }
    };
    // To assign the branch, try each method; return whatever doesn't fail.
    var testObject;
    try {
        testObject = standard.createXhrObject();
        return standard; // Return this if no error was thrown.
    }
    catch(e) {
        try {
            testObject = activeXNew.createXhrObject();
            return activeXNew; // Return this if no error was thrown.
        }
        catch(e) {
            try {
                testObject = activeXOld.createXhrObject();
                return activeXOld; // Return this if no error was thrown.
            }
            catch(e) {
                throw new Error('No XHR object found in this environment.');
            }
        }
    }
})();
 
 
// more rigorous implementation:
 
// BicycleShop class (abstract)
var BicycleShop = function(){};
BicycleShop.prototype = {
   sellBicycle: function(model) {
      var bicycle = this.createBicycle(model);
      bicycle.assemble();
      bicycle.wash();
      return bicycle;
   },
   createBicycle: function(model) {
      throw new Error('Unsupported operation on an abstract class.');
   }
};
// AcmeBicycleShop class
var AcmeBicycleShop = function() {};
extend(AcmeBicycleShop, BicycleShop);
 
AcmeBicycleShop.prototype.createBicycle = function(model) {
    var bicycle;
    switch(model) {
    case 'The Speedster':
        bicycle = new AcmeSpeedster();
        break;
    case 'The Lowrider':
        bicycle = new AcmeLowrider();
        break;
    case 'The Flatlander':
        bicycle = new AcmeFlatlander();
        break;
    case 'The Comfort Cruiser':
    default:
        bicycle = new AcmeComfortCruiser();
    }
    Interface.ensureImplements(bicycle, Bicycle);
    return bicycle;
};

Chaining

// With chaining:
$('example').addEvent('click', function() {
  $(this).setStyle('color', 'green').show();
});
 
(function() {
    // Use a private class.
    function _$(els) {
        this.elements = [];
        for (var i = 0, len = els.length; i < len; ++i) {
            var element = els[i];
            if (typeof element === 'string') {
                element = document.getElementById(element);
            }
            this.elements.push(element);
        }
    }
    // The public interface remains the same.
    window.$ = function() {
        return new _$(arguments);
    };
})();

Since all objects inherit from their prototype, you can take advantage of the reference to the instance object being returned and run each of the methods attached to the prototype as a chain. With that in mind, let's go ahead and add methods to the private dollar constructor prototype. This will make chaining possible:

(function() {
   function _$(els) {
      // private class constructor
   }
   // private prototype
   _$.prototype = {
      each: function(fn) {
         for ( var i = 0, len = this.elements.length; i < len; ++i ) {
            // handling callbacks
            fn.call(this, this.elements[i]);
         }
         return this;
      },
      setStyle: function(prop, val) {
         this.each(function(el) {
            el.style[prop] = val;
         });
         return this;
      },
      show: function() {
         var that = this;
         this.each(function(el) {
            that.setStyle('display', 'block');
         });
         return this;
      },
      addEvent: function(type, fn) {
         var add = function(el) {
            if (window.addEventListener) {
              el.addEventListener(type, fn, false);
            }
            else if (window.attachEvent) {
              el.attachEvent('on'+type, fn);
            }
         };
         this.each(function(el) {
            add(el);
         });
         return this;
      }
   };
   window.$ = function() {
      return new _$(arguments);
   };
})();

Bridge

Bridge pattern can be used to ensure that the dependent classes and objects are coupled to it loosely. As defined by the Gang of Four, a bridge should "decouple an abstraction from its implementation so that the two can vary independently."

// bridge on Event api
addEvent(element, 'click', getBeerById);
 
function getBeerById( callback ) {
    // bridge on xhr api
    asyncRequest('GET', 'beer.uri?id=' + this.id, function(resp) {
    // Callback response.
    callback( resp.responseText );
});

Observer

/*
var testSubscription = pubsub.subscribe( 'example1', function(args){} );
// Publishers are in charge of "publishing" notifications about events
pubsub.publish( 'example1', 'hello world!' );
pubsub.publish( 'example1', ['test','a','b','c'] );
*/
var Event = {};
(function(q) {
    var topics = {},
        subUid = -1;
 
    // Publish or broadcast events of interest
    // with a specific topic name and arguments
    // such as the data to pass along
    q.publish = function( topic, args ) {
        if ( !topics[topic] ) {
            return false;
        }
        var subscribers = topics[topic];
        var len = subscribers ? subscribers.length : 0;
        while (len--) {
            subscribers[len].func(topic, args);
        }
        return true;
    };
 
 
 
    // Subscribe to events of interest
    // with a specific topic name and a
    // callback function, to be executed
    // when the topic/event is observed
    q.subscribe = function( topic, func ) {
        if (!topics[topic]) {
            topics[topic] = [];
        }
        var token = (++subUid).toString();
        topics[topic].push({
            token: token,
            func: func
        });
        return token;
    };
 
    // Unsubscribe from a specific
    // topic, based on a tokenized reference
    // to the subscription
    q.unsubscribe = function( token ) {
        for ( var m in topics ) {
            if ( topics[m] ) {
                for (var i = 0, j = topics[m].length; i < j; i++) {
                    if (topics[m][i].token === token) {
                        topics[m].splice(i, 1);
                        return token;
                    }
                }
            }
        }
        return false;
    };
}( Event ));

Module

// v1
var MyMmodule = (function(){
 
    // private
    var _p = 1;
    function add(a, b){
        return a + b;
    }
 
    // public methods
    return {
        add: add
    };
})();
console.log(MyMmodule.add(1, 2));
 
// v2
module = function() {
    // ... module privates and aliases
 
    // public
    return {
        // ... module constants
        init: function() {
            return this;
        },
 
    };
}().init();

RequireJS module

define(function(){
    function add(a, b){
        return a + b;
    }
    return {
        add:add
    };
});
require(['MyMath'], function(MyMath){
    console.log(MyMath.add(1, 2));
});

AMD

CommonJS