旧それなりブログの跡地、画像やスタイルやJSなどが壊れてることがあります。

[JS] SingletonをMixinする関数

2008年9月15日

以前も何度かトライしていたが、イマイチ不完全燃焼で終わっていた
JavaScriptでのSingletonパターンの実装。

そういやRubyがMix-inで付加する形で付けてたなぁと
JavaScriptでそれを実装してみた。

// Mix-in singleton pattern.
var singleton = function(SomeClass){
    var NewClass = function(){
        throw new Error("This is Singleton-Pattern Class. Use self.getInstance().");
    };
    NewClass.__instance__ = null;
    NewClass.getInstance = function(){
        if (this.__instance__ === null) this.__instance__ = applyNew(SomeClass, arguments);
        return this.__instance__;
    }

    function applyNew(cls, args){
        var Tmp = function(){};
        Tmp.prototype = cls.prototype;
        var instance = new Tmp;
        cls.apply(instance, args || []);
        return instance;
    }
    return NewClass;
}

// This class is for the test.
var Person = function(name, age){
    this._name = name;
    this._age = age;
}
Person.prototype = {
    getName: function(){return this._name},
    getAge: function(){return this._age}
};
// Test
Person = singleton(Person);
//p = new Person; // -> Exception
var p1 = Person.getInstance("kjirou", 31);
alert(p1.getName()); // -> "kjirou"
alert(p1.getAge()); // -> 31
var p2 = Person.getInstance();
alert(p1 === p2); // -> true

おー!!

newの抑止も出来てるし、
prototype拡張をやるよりも影響が少ないし
概ね良いんじゃね?

これなら案件にも入れやすいので、後は使って試すかー。

何かご意見等あればよろしくお願いします!!

【蛇足的追記】
ちなみになんですが、唯一のインスタンスを完全に隠蔽したいのならこっち。
スクリプト言語畑で育った自分としては、ここまでせんでもとは思いますが・・・。
(クラスを消しても参照が残っちゃうのがキモチ悪い気がする)
お好みでどうぞ。

var singleton = function(SomeClass){
function applyNew(cls, args){
var Tmp = function(){};
Tmp.prototype = cls.prototype;
var instance = new Tmp;
cls.apply(instance, args || []);
return instance;
};
return (function(){
var INSTANCE = null;
var NewClass = function(){
throw new Error("This is Singleton-Pattern Class. Use self.getInstance().");
};
NewClass.getInstance = function(){
if (INSTANCE === null)
INSTANCE = applyNew(SomeClass, arguments);
return INSTANCE;
};
return NewClass;
})();
};