转自dhtmlkitchen

 Design Patterns in JavaScript

Singleton Design Pattern

The intent of the Singleton pattern as defined in Design Patterns is to "ensure a class has only one instance, and provide a global point of access to it".

This type of eager-load Singleton is useful for eager-load objects.

Disclaimer

Testing the userAgent header is not a good coding practice. It is error prone and forwards-incompatible. The fact that the function refers Netscape 4 indicates that it is quite old. The JavaScript technique, however, is practical and relevant.

For this example, consider an object class UserAgent, that does not use a Singleton pattern.

UserAgent = function UserAgent() {
var u = navigator.userAgent, d = document;
this.ie = typeof d.all != "undefined";
this.ns4 = typeof d.layers != "undefined";
this.dom = typeof d.getElementById != "undefined";
this.safari = /Safari/.test(u);
this.moz = /Gecko/.test(u) && !this.safari;
this.mie = this.ie && /Mac/.test(u);
this.win9x = /Win9/.test(u) || /Windows 9/.test(u);
this.o7 = /Opera 7/.test(u);
this.supported = (typeof d.write != "undefined")
&& (this.ie || this.ns4 || this.dom);
};
Now we have to instantiate this class:
var ua = new UserAgent();

The class may be instantiated again and again. This is not necessary, and probably won't cause a problem if we're careful.

Solution

The easiest solution is to create and invoke constructor in the same statement.

Solution

A simple solution is to create and call constructor in one statement.

ua = new function UserAgent() {
var u = navigator.userAgent, d = document;
this.ie = typeof d.all != "undefined";
this.ns4 = typeof d.layers != "undefined";
this.dom = typeof d.getElementById != "undefined";
this.safari = /Safari/.test(u);
this.moz = /Gecko/.test(u) && !this.safari;
this.mie = this.ie && /Mac/.test(u);
this.win9x = /Win9/.test(u) || /Windows 9/.test(u);
this.o7 = /Opera 7/.test(u);
this.supported = (typeof d.write != "undefined")
&& (this.ie || this.ns4 || this.dom);
};

We have just created and instantiated the class in one statement. The new operator creates an object of type UserAgent which is assigned to the variable ua.

Benefits Over Object Literal

  • Can have local variables closed in scope
  • Has a constructor property, which can be introspected during debugging.

Avoid Anonymous Constructors!

An anonymous constructor has no name. See for yourself: Click the link below.

alert(new function(){ this.foo = "bar"; }.constructor);

It is much easier to debug named objects. Anonymous functions are hard to debug and will show up in JavaScript debuggers as noname or function. Please name your functions.

There you have it. The Singleton pattern in JavaScript. Simple, efficient, elegant. It is very useful and very easy to implement.