JavaScript Factory Design Pattern
The Factory
design pattern separates object creation from the rest of code. When creation of an object is complex or a subject to a change, a factory acts as a nice mediator. However factory needs a good design as it may lead to class explosions. A simple factory
is an object which implements the creation of another object, acting as a shield from the rest of application.
var vessel = VesselFactory.createVessel();
Usually we have a parameter which gives a clue to the simple factory about the detail creation class:
var submarine = VesselFactory.createVessel('submarine'); var tanker = VesselFactory.createVessel('tanker');
Therefore the factory implementation looks like:
VesselFactory.createVessel = function(type) { if (type == 'submarine') { return new Submarine(); } else if (type == 'tanker') { return new Tanker(); } }
The return value of the factory is called a product
. It's essential that products submarine
and tanker
keep a consistent interface so that clients can use any product from the factory not needing to check if a product method exists. That pattern can be extended through the use of Factory Method. Factory Method
defines an interface for creating object, but let the subclasses decide which class to instantiate. In other words a method is overriden in each subclass and decides what to return. Products abide interfaces that clients can use them.
<script text="text/javascript"> //specify create method if not present if (!Object.create) { Object.create = function(obj) { if (arguments.length > 1) { throw "Too many arguments..."; } function target() {} target.prototype = obj; return new target(); } } var createObject = function(prototype, object) { var target = Object.create(prototype); for (var prop in object) { if (object.hasOwnProperty(prop)) { target[prop] = object[prop]; } } return target; }; //product var vessel = { type: 'vessel' }; //base factory var vesselFactory = { createVessel: function() { return new vessel(); } }; //subclass var submarineFactory = createObject(vesselFactory, { //override method to return submarine product createVessel: function() { return createObject(vessel, { type: 'submarine' }); } }); var vessel = submarineFactory.createVessel(); console.log(vessel.type); </script>
Unlike Factory Method, Abstract Factory
pattern defines any number of methods which return products. That pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes or some might think of it as composed of many Factory Methods.
<script text="text/javascript"> //base factory var shipFactory = { createTanker: function() { return 'tanker, model T45'; }, createCruiser: function() { return 'cruiser, model C35'; } }; shipFactory.createNextGeneration = function() { return createObject(shipFactory, { createTanker: function() { return 'tanker, model T55'; }, createCruiser: function() { return 'cruiser, model C45'; } }); }; var newFactory = shipFactory.createNextGeneration(); console.log(newFactory.createTanker()); </script>