シングルトンクラスを量産する
Backbone.jsを使ってシングルトンパターンを作る場合、
以下のようにconstructorを書いてやるといいらしい。
var Singleton = Backbone.Model.extend({
constructor: function(){
if(!Singleton.instance){
Singleton.instance = this;
Backbone.Model.apply(Singleton.instance, arguments);
}
return Singleton.instance;
}
});
そして、以下のようにしてChromeか何かでコンソールを表示して確認するとうまくいっているのがわかる。
var obj = new Singleton({
foo: "foo"
});
var obj2 = new Singleton();
console.log(obj.toJSON());
console.log(obj2.toJSON());
毎回、シングルトンを書くのが面倒くさいという場合は、
クラスSingletonを以下のように変更して、
var Singleton = Backbone.Model.extend({
constructor: function(){
var self = this.__proto__.constructor;
if(!self.instance){
self.instance = this;
Backbone.Model.apply(self.instance, arguments);
}
return self.instance;
}
});
以下のように使えば、シングルトンクラスを量産可能ではある…。
var AnotherSingleton = Singleton.extend();
var s1 = new Singleton({foo: "Singleton"});
var s2 = new Singleton();
var a1 = new AnotherSingleton({foo: "AnotherSingleton"});
var a2 = new AnotherSingleton();
console.log(s1.toJSON());
console.log(s2.toJSON());
console.log(a1.toJSON());
console.log(a2.toJSON());
シングルトンクラスと継承
Javaなどのシングルトンパターンでは、シングルトンクラスから
子クラスを作ることはない。
大抵は、シングルトンクラスのコンストラクタメソッド自体を
privateにして子クラスを作成できなくしてしまう。
なぜ、子クラスを作れなくしてしまうかというと、
思うに、
・シングルトンとはただ1つのインスタンスしか持たない
というのと、
・子クラスで(親クラスとは)別のインスタンスを作りたい
という考えの整合がとれないからだろう。
もし、子クラスが作れたとして、その子クラスのインスタンスも
親クラスのインスタンスとみなせるので、
「親クラスのインスタンスは1つだけ」という原理原則から考えると、
子クラスのインスタンスも親クラスのインスタンスと同一のもので
なければいけなくなる。
そうなると、そもそも子クラスを作る必要がなくなる。
(子クラスでインスタンスを作っても、親クラスでインスタンスを
作っても同じインスタンスになるなら、子クラスは必要ない。)
では、子クラスでは親クラスとは別の属性を付け加えたい場合は
どうすればよいのだろう?
これは、シングルトンクラスを継承して属性を追加したい、
という意味になる。
なんか混乱してくるけど、これは、ずばりクラスの設計がおかしい。
この場合の解決策は、シングルトンクラスのインスタンスを
メンバーに持った新たなクラスを作るのが正解だろう。
つまり、こんな感じ。
var Singleton = Backbone.Model.extend({
constructor: function(){
if(!Singleton.instance){
Singleton.instance = this;
Backbone.Model.apply(Singleton.instance, arguments);
}
return Singleton.instance;
}
});
var obj = new Singleton({
type: "singleton"
});
var MyClass = Backbone.Model.extend({
singleton: new Singleton(),
defaults: {
item1: "foo",
item2: "bar"
}
})
var MyClass2 = MyClass.extend();
var obj2 = new MyClass();
var obj3 = new MyClass2({
item1: "zot"
});
console.log(obj.toJSON());
console.log(obj2.toJSON());
console.log(obj3.toJSON());
console.log(obj2.singleton.toJSON());
console.log(obj3.singleton.toJSON());