Design Patterns in JavaScript, Part 1 | WebReference

Design Patterns in JavaScript, Part 1

Design Patterns in JavaScript, Part 1

By Nicholas C. Zakas.

For those who come from a traditional object-oriented programming background, you may already know a lot about design patterns. A design pattern is a programming solution to a specific problem that has been documented so that the developer doesn't need to solve the same problem again. The basic idea is that there are simple problems that developers come across in the course of implementing larger solutions, and that standard patterns can be used to free the developer from spending time reworking these simple problems.

Several books on design patterns are currently available, and many focus on a common set of patterns that can be applied to any object-oriented programming language. Since JavaScript falls into this category, this series of articles will explore implementing several popular design patterns in JavaScript.

Creational Patterns

The first type of design pattern to explore is the creational pattern. As you may have guessed, a creational pattern deals with the creation of objects within a program. The common way of creating objects in JavaScript is in the following manner:

var oMyObject = new MyClass();

Most of the time, you have no reason to do this in any other way. You simply define your class and then instantiate it later. However, there are some times when this isn't advantageous or desired.

Factory Pattern

Suppose that you don't know the exact class that should be created until runtime. In the case of JavaScript, this may be due to browser differences. If it's Internet Explorer, you need to create an instance of one class; if it's not (IE), you need to create another. The key is that the returned object has the same interface (properties and methods) regardless of which class is instantiated. Since JavaScript is loosely typed and has no concept of interfaces, you need to trust that the returned object will have the properties or methods you need to get the job done. The best example of this today is in creating XMLHttp objects. A lot of times, you'll see code that looks like this:

if (typeof XMLHttpRequest != "undefined") {
    return new XMLHttpRequest();
} else if (typeof window.ActiveXObject != "undefined") {
    return new ActiveXObject("MSXML2.XMLHttp");
}

Clearly, you don't want to repeat this code every time you need to create a new XMLHttp object. Aside from creating a lot of extra code, it's impossible to keep the code in sync should another condition be introduced that would return a third type of object. This is when you would use the factory pattern.

The factory pattern involves having a function (or an object with a method) that returns the appropriate object. Developers need not know which object is being returned since the interface will be the same no matter what. You need only call the function and know that the correct object will be returned. For example:

function XMLHttpFactory() {
}

XMLHttpFactory.createXMLHttp = function () {
    if (typeof XMLHttpRequest != "undefined") {
        return new XMLHttpRequest();
    } else if (typeof window.ActiveXObject != "undefined") {
        return new ActiveXObject("MSXML2.XMLHttp");
    }
}

With this defined, developers can now use a single method call to create the object that will work for their environment:

var oXMLHttp = XMLHttpFactory.createXMLHttp();

If any other conditions become necessary, these can be addressed in a single location without impacting code that has been written using XMLHttp objects.

In many object-oriented programming languages, classes returned from factories typically have private or protected constructors so that they can't be instantiated directly from outside the class or package. Since JavaScript has no concept of non-public constructors, you'll need to use a different approach if this is a concern.

Suppose that you have a class called MyClass, which should only be instantiated from a factory method, MyFactory.createObject(), such as:

function MyClass() {
   this.myproperty = "hello world";
}

function MyFactory {}

MyFactory.createObject = function () {
    return new MyClass();
}

You want to prevent a developer from writing this:

var oMyObject = new MyClass();

The truth is, you can't stop a developer from writing this code. Unlike traditional languages with protected or private constructors, there is no compilation step to catch the offense. Instead, you need to provide the error telling the developer that this is an illegal action. But how do you do that?

Looking at the code again, what you really want to do is make sure that a MyClass instance can only be created inside of the MyFactory.createObject() method. Is there a way to tell at runtime what function or method is trying to create the object? The answer is yes.

Each function has a caller property that points to the function that is calling it. So all you really need to do is ensure that the caller is the factory method and throw an error if it isn't, like this:

function MyClass() {
   if (MyClass.caller != MyFactory.createObject) {
       throw new Error("There is no public constructor for MyClass.");
   }

   this.myproperty = "hello world";
}

In this code, you are ensuring that constructor is being called from within the MyFactory.createObject() method by checking the caller property. If caller is set to something other than that function, an error is thrown stating that there is no public constructor for the class. While not as strict as a private or protected constructor in a compiled language, it has the same effect of enforcing usage of the factory.

Key points to remember about the factory pattern:


Created: March 27, 2003
Revised: April 21, 2006

URL: http://webreference.com/programming/javascript/ncz/column5/1