JavaScriptでちょっと変わったシングルトン

シングルトンって何?

シングルトンとは、あるクラスから生成されるインスタンスを一つに抑えるためのデザインパターンです。このパターンを使うことで、無駄に新しいインスタンスを生成するのを抑えます。今回、最速インターフェース研究会のJavaScriptのデザインパターン - Singletonを参考にして、少し違ったシングルトンの例を書いてみました。通常のシングルトンは、1つのクラスに対して、1つのインスタンスを保障するものです。しかし、今回私が書いたのは、クラスのコンストラクタに渡す引数の値に応じて、1つのインスタンスを保障するものです。

今回のサンプルで利用するのは、Pointというある座標(x,y)を表すクラスです。通常以下のようにしてPointクラスからインスタンスを生成しようとすると、newした回数だけ新しいインスタンスが作られます。

var Point = function(x,y){
	this.x = x;
	this.y = y;
}

var p1 = new Point(3,5);
var p2 = new Point(6,3);
var p3 = new Point(-2,1);

しかし、次のように座標(x,y)が同じでも、違うオブジェクトが生成されてしまいます。

var p1 = new Point(3,5);
var p2 = new Point(3,5);

if(p1 != p2){
	alert("p1とp2は違う");
}

そこで、座標が同一の場合、同じオブジェクトを返すようにします。これによって無駄なオブジェクトの生成をおさえます。

問題を解決

今回、Pointクラス(コンストラクタ)のプロトタイプに対して、今まで作った座標の一覧を持たせます。newキーワードでPointクラスが呼ばれると、指定された座標を表すオブジェクトが、すでに作られているのかどうか、一覧の中から探します。すでに作られているなら、それを返します。逆に、作られていないなら、新たに生成します。

var Point =function(x,y){
	if (!arguments.callee.prototype) {
		arguments.callee.prototype = {};
	}
	var proto = arguments.callee.prototype;
	if(!proto.points)
		proto.points = [];
	for(var i=0; i <proto.points.length ; i++){
		var p = proto.points[i];
		//すでに定義済みなら
		if (p.x == x && p.y == y) {
			return p;
		}
	}
	//クラス
	var P = function(x,y){
		this.x = x;
		this.y = y;
	};
	var p = new P(x,y);
	proto.points.push(p); //一覧に追加
	return p;
};

使い方は以下のようになります。

var p1 = new Point(1,2);
var p2 = new Point(1,2);
var p3 = new Point(1,3);

if(p1 == p2){
	alert("p1とp2は同じ");
}

if(p1 != p3){
	alert("p1とp3は違う");
}