Wednesday, April 14, 2010

JavaScript Design Patterns - Interface

I read the book couple of times, and would like to post simple summaries on the topics that are written in the book and post some examples (add some more later). I like the book, but it's sometimes very high level descriptions of pro and cons that need more practical usage.

You can buy this book here: Pro JavaScript Design Patterns by Ross Harmes and Dustin Diaz, publisher Apess.

Let's start with Interface.

An Interface provides a way of specifying what methods an object should have.

It does not specify how those methods should be implemented.
This is typical definition for other object oriented languages (i.e. java).

Three ways of emulating interfaces in javascript:

comments

attribute checking

duck typing


The interface class:
// Constructor.
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++) {
  //book's example uses interface word, this is reserved word, so I changed it.
        var interFaceObjectArray = arguments[i];
        if(interFaceObjectArray.constructor !== Interface) {
            throw new Error("Function Interface.ensureImplements expects arguments "   
              + "two and above to be instances of Interface.");
        }
        
        for(var j = 0, methodsLen = interFaceObjectArray.methods.length; j < methodsLen; j++) {
            var method = interFaceObjectArray.methods[j];
            if(!object[method] || typeof object[method] !== 'function') {
                throw new Error("Function Interface.ensureImplements: object " 
                  + "does not implement the " + interFaceObjectArray.name 
                  + " interface. Method " + method + " was not found.");
            }
        }
    } 
};

Best usage for Interfaces: It becomes most beneficial when you start implementing complex systems usings design patterns. It might seem like interfaces reduce JavaScript's flexibility, but they actually improve it by allowing your objects to be more loosley coupled. Your functions can be more flexible because you can pass in arguments of any type and still ensure that only objects with the needed method will be used. Patterns That Rely on the Interface: - Factory Pattern The specific objects that are created by a factory can change depending on the situation. In order to ensure that the objects created can be used interchangeably, interfaces are used. "...This means that a factory is guaranteed to produce an object that will implement the needed methods...." (sounds like from java book.) - Composite Pattern You can't use this pattern without an interface. The most important idea behind the composite is that groups of objects can be treated the same as the constituent objects. This is accomplished by implementing the same interface. - Decorator Pattern A decorator works by transparently wrapping another object. This is accomplished by implementing the exact ame interface as the other object; from the outside, the decorator and the object it wraps look identical. We use the Interface class to ensure that any decorator objects created implement the needed methods. - Command Pattern All command objects within your code will implement the same methods (like execute, run, etc). By using interfaces, you can create classes that can execute these commands without needing to know anything about them, other than the fact that they implement the correct interface. This allows you to create extremely modular and loosely coupled user interfaces and API's. I started from the last one, I will redo this page and add more info to explain the Command Pattern and others as time permits. The goal is to bring it from theory into more everyday things. Others are using it to build complex systems already, but I feel it needs more discussion and to spread the word. Here is another quote from the book:
The first principle of reusable object-oriented design mentioned in the Gang of Four's Design Patterns says "Program to an interface, not an implementation," telling you how fundamental this concept is.
Please check out the Command Pattern demo here. Here to Download.

No comments:

Post a Comment