読者です 読者をやめる 読者になる 読者になる

webネタ

技術系ブログ。web系SE。1988。♂。@rhong_

JavascriptでSingletonパターン

Singletonで実装したい要件があったが、ググッっても良いのがなくて本読んでも残念なものしかなかったので自分で実装してみた。ちなみに本は、JavaScriptパターン ―優れたアプリケーションのための作法

要件

  • newできないようにする。
  • 同一オブジェクトを返す。

クラス名は本にあったものと同じUniverseにしたが別になんでもok。

最初にテストコード

newできないか
try {
    new Universe()
} catch(e) {
    console.info("ok", e);
}

new したら例外が吐かれるようにする。

同一オブジェクトか
var u1 = Universe.getInstance();
var u2 = Universe.getInstance();
console.info(“true?”, u1 === u2);
console.info(“true?”, u2.constructor === Universe);

厳密な等価 + constructorも同じかチェックするる

いつもはjasmineでテスト書くけど今回は準備がめんどうなのでベタ書き。

実装

/**
 * Description of this class.
 * Singleton Class.
 * 
 * @class Universe
 */
var Universe = (function() {
	
	var _fromGetInstance = false;
	var _instance;
	
	function _construct() {
	    if (_fromGetInstance !== true) {
	        throw new Error("must use the getInstance.");
	    }
	    _fromGetInstance = false;
	}
	
	/**
         * @method getInstance
         * @return {Object}
         */
	_construct.getInstance = function() {
	    if (_instance) {
	        return _instance;
	    }
	    _fromGetInstance = true;
	    return _instance = new this();
	}
	return _construct;
})();

/**
 * func1.
 * 
 * @method func1
 */
Universe.prototype.func1 = function() {
    console.log("called func1");
}

使い方

var universe = Universe.getInstanse();
universe.func1();


まず、privateにしたいプロパティがあったのでクロージャにした。
returnされるfunctionをnewできないようにしたいので、getInstanceメソッドからでなければ呼べないようにしてしまう。判定方法は、変数_fromGetInstanceがtrueなのかfalseかなのかというだけ。getInstanceでは一度生成したら次からはそのインスタンスを返すだけ。phpの実装と似た感じ。あとはprotptypeに実装したいメソッドを書いていけばてつもどおりになる。

本の場合

ちなみに本に載ってたsingletonは下記のようにnew Universe()するが、返すものは同じという謎な仕様だった。

var u1 = new Universe();
var u2 = new Universe();
console.info(“true?”, u1 === u2); // true

なんぞこれ。カオスすぎる。


次はfactory書く。