TL;DR: This article provides an in-depth understanding of the factory pattern in JavaScript and how it’s used to create objects. Factory patterns encapsulate the logic of creating complex objects, making it easier to manage and extend objects when required.
Introduction: The factory pattern is a creational design pattern that provides an interface for creating objects in a super class, but allows subclasses to alter the type of objects that will be created. Essentially, a factory is a collection of objects that construct other objects based on input parameters.
Body:
Why use the Factory pattern? The Factory pattern promotes loose coupling and scalability, which are crucial for maintaining and extending the codebase. It simplifies the creation of complex objects by moving this logic into one location, reducing the need for repetitive code.
Implementing the Factory Pattern:
- Step 1 – mediaFactory.js: This file represents our factory. It contains the logic for creating instances of media objects (e.g., Video, Image), depending on the ‘type’ parameter provided.
define(function (require) { 'use strict'; var media = { Video: require('factory/video'), Image: require('factory/image') }; return { createMedia: function (type, attributes) { var MediaType = media[type]; return new MediaType(attributes); } }; });
- Step 2 – image.js: This file defines the Image object that the factory can create. The Image object has attributes such as width, height, and name.
define(function () { 'use strict'; var Image = function (attributes) { this.width = attributes.width || 0; this.height = attributes.height || 0; this.name = attributes.name || ''; }; return Image; });
- Step 3 – video.js: Similar to image.js, this file defines the Video object. The Video object has attributes such as length and name.
define(function () { 'use strict'; var Video = function (attributes) { this.length = attributes.length || 0; this.name = attributes.name || ''; }; return Video; });
- Step 4 – main.js: This file is used to run examples. The
runExample
function is attached to the global window object and can be used to execute any example available in theexamples
object.
require ( ['factory/init', 'pubSub/init', 'strategy/init', 'observer/init'], function (factory) { 'use strict'; var examples = { factory: factory }; window.runExample = function (example) { examples[example].init(); }; } );
- Step 5 – init.js: This file is where we make use of our
mediaFactory
to create instances of Video and Image objects.
define(function(require) { 'use strict'; return { init: function() { var myVideo, myImage, mediaFactory = require('factory/mediaFactory'); myVideo = mediaFactory.createMedia('Video', { length: 3.5, name: 'My video' }); myImage = mediaFactory.createMedia('Image', { width: 100, height: 11, name: 'My Image' }); console.log(myVideo); console.log(myImage); } }; });
Conclusion: The Factory pattern is a highly useful design pattern in JavaScript. It encapsulates the creation of objects, decoupling the process of object construction from the client that requires the object instances. By implementing the Factory pattern in your JavaScript code, you simplify object creation, especially for complex objects, and make it easier to extend the types of objects that your code can produce.