日期:2014-05-16  浏览次数:20309 次

JavaScript Patterns 读书笔记(六)

6.Design Pattern

  • Singleton
    ??? The idea of the singleton pattern is to have only one instance of a specific class. This means that the second time you use the same class to create a new object, you should get the same object that was created the first time.
    ?? And how does this apply to JavaScript? In JavaScript there are no classes, just objects.When you create a new object, there’s actually no other object like it, and the new object is already a singleton. Creating a simple object using the object literal is also an example of a singleton:
    var obj = {
    	myprop: 'my value'
    };
    ???? In JavaScript, objects are never equal unless they are the same object, so even if you create an identical object with the exact same members, it won’t be the same as the first one:
    var obj2 = {
    	myprop: 'my value'
    };
    
    obj === obj2; // false
    obj == obj2; // false
    
    ??? So you can say that every time you create an object using the object literal, you’re actually creating a singleton, and there’s no special syntax involved.

    Using new
    ???? JavaScript doesn’t have classes, so the verbatim definition for singleton doesn’t technically??? make sense. But JavaScript has the new syntax for creating objects using constructor??? functions, and sometimes you might want a singleton implementation using this syntax. The idea is that when you use new to create several objects using the same constructor, you should get only new pointers to the exact same object. The following snippet shows the expected behavior (assuming that you dismiss the idea of the Multiverse and accept that there’s only one Universe out there):
    var uni = new Universe();
    var uni2 = new Universe();
    uni === uni2; // true
    
    ???? In this example, uni is created only the first time the constructor is called. The second time (and the third, fourth, and so on) the same uni object is returned. This is why uni === uni2—because they are essentially two references pointing to the exact same object. And how to achieve this in JavaScript?
    ??? You need your Universe constructor to cache the object instance this when it’s created and then return it the second time the constructor is called. You have several options to achieve this:

    ?????? ? You can use a global variable to store the instance. This is not recommended because of the general principle that globals are bad. Plus, anyone can overwrite this global variable, even by accident. So let’s not discuss this option any further.

    ??? ?? ? You can cache in a static property of the constructor. Functions in JavaScript are objects, so they can have properties. You can have something like Universe.instance and cache the object there. This is a nice, clean solution with the only drawback that the instance property is publicly accessible, and code outside of yours might change it, so you lose the instance.

    ??? ?? ? You can wrap the instance in a closure. This keeps the instance private and not available for modifications outside of your constructor at the expense of an extra closure.

    Let’s take a look at an example implementation of the second and third options.

    Instance in a Static Property
    ? ? ?? Here’s an example of caching the singular instance in a static property of the Universe constructor:
    function Universe() {
    	// do we have an existing instance?
    	if (typeof Universe.instance === "object") {
    		return Universe.instance;
    	}
    	// proceed as normal
    	this.start_time = 0;
    	this.bang = "Big";
    	// cache
    	Universe.instance = this;
    	// implicit return:
    	// return this;
    }
    
    // testing
    var uni = new Universe();
    var uni2 = new Universe();
    uni === uni2; // true
    
    ??? As you see, this is a straightforward solution with the only drawback that instance is public. It’s unlikely that other code will change it by mistake (mu