GitHub LinkedIn RSS
Sunday, July 27, 2014

JavaScript Builder Design Pattern


Today I would like to continue the series about design patterns we started with Factory Patterns in JavaScript and talk about the Builder pattern. For some reason it's being left behind in any design pattern usage in JavaScript. Maybe it was correct in the front end domain, but surely not in Node.js.

Builder pattern separates the construction of a complex object from its representation so that the same construction process can create different representations. The Builder pattern is based on Directors and Builders. Any number of Builder classes can conform to an IBuilder interface, and they can be called by a director to produce a product according to specification. The builders supply parts that the Product objects accumulate until the director is finished with the job. I'll be using the example from the factory pattern article to emphasize the differences between the patterns. Consider the class diagram for the Builder pattern:


And the implementation:
function FastCPU() {
    this.performOperation = function() {
        console.log("Operation will perform quickly");
    }
}
function SlowCPU() {
    this.performOperation = function() {
        console.log("Operation will perform slowly");
    }
}
 
function ExpensiveMotherBoard() {
    this.storeData = function() {
        console.log("There is a lot of RAM to store the data");
    }
}
 
function CheapMotherBoard() {
    this.storeData = function() {
        console.log("Little RAM. Swap file is used");
    }
}
 
function HighBudgetMachineBuilder() {
    this.getCPU = function() { return new FastCPU(); }
    this.getMotherBoard = function() {
     return new ExpensiveMotherBoard();
    }
}
 
function LowBudgetMachineBuilder() {
    this.getCPU = function() { return new SlowCPU(); }
    this.getMotherBoard = function() {
     return new CheapMotherBoard();
    }
}

function Director() {
    this.assembleMachine = function(builder) {
        var cpu = builder.getCPU(), 
        board = builder.getMotherBoard();
        return {
            cpu: cpu,
            board: board,
            test: function test() {
                this.cpu.performOperation();
                this.board.storeData();
            }
        }
    }
}
 
var director = new Director(),
    highBuilder = new HighBudgetMachineBuilder(),
    lowBuilder = new LowBudgetMachineBuilder(),
    highMachine = director.assembleMachine(highBuilder);
    lowMachine = director.assembleMachine(lowBuilder);
highMachine.test();
lowMachine.test();
We've added the director which assembles the machine. The client on the other hand, is not aware of the process of assembling the machines. It only uses the Director's method to do so.

The Builder and Abstract Factory patterns are similar in that they both look at construction at an abstract level. However, the Builder pattern is concerned with how a single object is made upby the different factories, whereas the Abstract Factory pattern is concerned with what products are made. The Builder pattern abstracts the algorithm for construction by including the concept of a director. The director is responsible for itemizing the steps and calls on builders to fulfill them. Directors do not have to conform to an interface.