まめージェント

Android, GAE, AngularJSの技術ネタ中心。Twitter: @mame01112

Javascriptでデザインパターン (その4: Prototype)

続いてPrototypeパターン。

これで4つ目。

Singleton, Factory, Mediatorに関しては下記参照。

Singleton: http://mame0112.hatenablog.com/entry/2015/07/26/130425
Factory: http://mame0112.hatenablog.com/entry/2015/07/26/195821
Mediator: http://mame0112.hatenablog.com/entry/2015/07/26/210249

Prototypeパターンって?

同じようなインスタンス複数作るときに使うデザインパターンです。Javaではいまだにそんなユースケースに出会ったことないですが。。。
Javascriptの継承で使う"prototype"と、このデザインパターンの"Prototype"は同じ意味合い(日本語訳だと、”試作品”よりは”原型”ですね)のようです。

プログラマ的なメリットは、同じようなインスタンスを作るときに、コンストラクタの引数を少しずつ変えて作る必要がなくなり、テンプレートとなるインスタンスから作れて工数削減やケアレスミス防止につながる部分ですね。

また、”同じようなインスタンスを作る”という意味では、Builderパターンにも近いですね。Builderパターンではイチからインスタンスを作る場合と、(例えば)createFrom()というメソッドの引数に原型となるインスタンスを渡してそのインスタンスに対してsetしていく、という使い方もしたりするので。話がそれました。

サンプルコード

そんなに説明することもないので、早速サンプルコード。

var Prototype = function(){

	//Template values
	this.id = 0;
	this.name = "test name";
	this.property1 = "prop1";
	this.property2 = "prop2";

};

Prototype.prototype = {
	clone : function(){
		console.log("clone");
		return new Prototype(this.id, this.name, this.property1, this.property2);
	},

	setId: function(id){
		this.id = id;
	},

	setName: function(name){
		this.name = name;
	},

	getResult: function(){
		console.log("id: " + this.id + " name: " + this.name + " property1: " + this.property1 + " property2: " + this.property2);
	}
};

var typeA = new Prototype();
typeA.getResult(); // id: 0 name: test name property1: prop1 property2: prop2

var typeB = typeA.clone();
typeB.setId(2);
typeB.setName("test name2");

typeA.getResult(); // id: 0 name: test name property1: prop1 property2: prop2
typeB.getResult(); // id: 2 name: test name2 property1: prop1 property2: prop2

キモは、cloneメソッド内でインスタンスを作っているところですかね。ここで新しいインスタンスを作らないと、同じ値を参照してしまい、意図せぬ挙動になります。また、最近(??はnewの代わりにObject.create()を使うべき(すでにnewを使うのはアンチパターンとか・・・?)という話もあるので、この部分は今後調べたみようと思います(この部分も結構奥が深い・・・)

また、(他のパターンも然りですが)このデザインパターンJavascriptではいろんな書き方ができそうですね。ので、今回のはあくまで一例ということで。