いろいろなSingletonを実装してみます。
関数
var getSingleton = (function() { var instance = null, init = function() { instance = { value: Math.random() } }; return function() { if (instance == null) { init(); } return instance; }; })(); var a = getSingleton(); var b = getSingleton(); console.log(a == b); //true console.log(a.value == b.value); //true var c = Object.create(a); console.log(a == c); //false console.log(a.value == c.value); //true
JavaScript デザインパターンの実装から関数を抜いてきただけなので同じ動きです。
Sigleton属性を継承する
var singleton = (function() { return { getObject: function() { if (this.instance === undefined && typeof(this.init) === 'function') { this.instance = this.init(); } return this.instance; } }; })(); var mySingleton = Object.create(singleton, { init: { value: function() { return { value: Math.random() }; } } }); var mySingleton2 = Object.create(singleton, { init: { value: function() { return { value: 1 }; } } }); var a = mySingleton.getObject(); var b = mySingleton.getObject(); console.log(a === b); //true console.log(a.value === b.value); //true var c = Object.create(a); console.log(a === c); //false console.log(a.value === c.value); //true var d = mySingleton2.getObject(); console.log(a === d); //false console.log(a.value === d.value); //false
singletonオブジェクトを継承して、固有の初期化メソッドを拡張できます。 でも、シングルトンをたくさん作るコードは捨てた方がいいです。
継承より委譲
Rubyにはmodule Singleton があってかっこいいので 真似してみます。
var getObject = function () { if (this.instance === undefined) { this.instance = Object.create(this); } return this.instance; } var a = { value : Math.random(), getObject : getObject }
インスタンス化の統一インタフェースがないのでObject.createを使ってみました。 でも、先にaオブジェクトを作る時点で、もう一度Object.createする必要がありません。 我ながら修行の足りなさを実感、まだクラス悩から解脱できません。