LoginSignup
17
16

More than 5 years have passed since last update.

Essential JavaScript Design Patterns For Beginners (作者:Addy Osmani)

Last updated at Posted at 2012-12-26

JavaScriptデザインパターン:The Singleton Pattern

JavaScriptの勉強にすごく役に立つので、JavaScriptを勉強したい人にはお勧めです。

The Singleton Pattern パターンは、コンストラクタを private とすることで、他関数から新たにインスタンスが生成されないような構造とすることで、インスタンスの生成を制御します。

※The Singleton Patternサンプルソース

var SingletonTester = (function() {

    // args: an object containing arguments for the singleton
    function Singleton(args) {

        // set args variable to args passed or empty object if none provided.
        var args = args || {};
        //set the name parameter
        this.name = 'SingletonTester';
        //set the value of pointX
        this.pointX = args.pointX || 6; //get parameter from arguments or set default
        //set the value of pointY
        this.pointY = args.pointY || 10;

    }

    // this is our instance holder
    var instance;

    // this is an emulation of static variables and methods
    var _static = {
        name: 'SingletonTester',
        // This is a method for getting an instance
        // It returns a singleton instance of a singleton object
        getInstance: function(args) {
            if (instance === undefined) {
                instance = new Singleton(args);
            }
            return instance;
        }
    };
    return _static;
})();

var singletonTest = SingletonTester.getInstance({
    pointX: 5
});
console.log(singletonTest.pointX); // outputs 5​

勉強・分析・まとめ:

The Singleton Patternを見たら、最初は私と同じチンプンカンプンだった人はいませんか。実はこのパターンを習得するために、下記の4つの知識が必要です。

1.コンストラクター

The Constructor Patternで説明をしましたが、下記の関数はコンストラクターであり、new演算子と組み合させてオブジェクトの生成時に使います。

function Car( model, year, miles ){
   this.model = model;
   this.year    = year;
   this.miles  = miles;
}

これで、上記The Singleton Patternサンプルソースはコンストラクターでオブジェクトを生成したことが分かります。

2.オブジェクトリテラル

The Creational Patternの中にもありますが、この{Key1:値, Key2:function(){], Key3:[値1,値2...] ,...}の形でオブジェクトを生成します。難しい概念を覚えるよりは、下記の形のソースは属性と関数を持つオブジェクトの生成をやっていると理解すればよいかと思います。(ちなみに、このオブジェクトリテラルはJSONによく似ています。
大きな違いとしては、オブジェクトリテラルはJSONの下記の制限がない。
・JSON は、文字列のクオートにダブルクオートしか使えない
・JSON は、キーのダブルクオートを省略できない
・JSON は、「数値」「文字列」「真偽値(true、false)」「配列」「オブジェクト」「null」のデータ型
 を利用することができますが、関数を利用することができない
・JSON は、コメントが書けない

var mySingleton = {
    property1: "something",

    property2: "something else",

    method1: function() {
        console.log('hello world');
    }

};

これで、上記The Singleton Patternサンプルソースの戻り値はオブジェクトリテラルであることが分かります。

3.クロージャ(クロージャー、closure(覚え方:close のsとeの間にurを入れる)、閉包)

クロージャを説明する前に、まず上記のオブジェクトリテラルを理解できたら、下記のソースがオブジェクトリテラルをreturnされ、その結果関数(publicMethod)と属性(publicVar)を持っているオブジェクトが生成されたことがわかります。

次にクロージャをちょっと説明します。クロージャとは関数が定義された環境への参照を持った関数のことです。下記のソースをベースに概念を書き換えるとこうなります。クロージャとは関数(mySingleton)が定義された環境(関数(showPrivate)と変数(privateVariable))への参照を持った関数(publicMethod)のことです。(showPrivate()も関数の中で定義されている関数なので、これもクロージャーであり、mySingleton()関数で定義されているprivateVariableをアクセスできます。)

(注意:下記のサンプルに示すmySingleton()関数は呼び出されるたびに新しいオブジェクトを返すため、まだシングルトンになっていません。)

function mySingleton() {

    // here are our private methods and variables
    var privateVariable = 'something private';

    function showPrivate() {
        console.log(privateVariable);
    }

    // public variables and methods (which can access 
    // private variables and methods )
    return {

        publicMethod: function() {
            showPrivate();
            privateVariable = "newValue";
        },

        publicVar: 'the public can see this!'

    };
};

var single = mySingleton();
single.publicMethod(); // logs 'something private'
console.log(single.publicVar); // logs 'the public can see this!'

これで、上記The Singleton Patternサンプルソースの戻り値であるオブジェクトリテラルの中で定義されているメソッドがクロージャとなり、外側の関数で定義された環境(Singleton(args)関数とinstance変数)を参照できることが分かります。

4.匿名関数・即時関数

匿名関数とは名前がない関数のことです。無名関数とも言います。
例:var Singleton = function(){};の右側が匿名関数となります。
即時関数とは定義してすぐに実行される関数のことです。
例:var Singleton = (function(){//ここに処理を記述します。})();

クロージャの説明で示したソースはシングルトンになっていないですが、下記のように変更したら、シングルトンになります。

var Singleton = (function() {
    var instantiated;

    function init() {
        // singleton here
        return {
            publicMethod: function() {
                console.log('hello world');
            },
            publicProperty: 'test'
        };
    }

    return {
        getInstance: function() {
            if (!instantiated) {
                instantiated = init();
            }
            return instantiated;
        }
    };
})();

// calling public methods is then as easy as:
Singleton.getInstance().publicMethod();

これで上記The Singleton Patternサンプルソースは即時関数であり、常に同じオブジェクトを返すことが分かります。

※私もまだまだの身ですが、誤情報の発信を防ぐために、上記の記述の中に間違いとかあれば、ご指摘をお願いします。そろそろ2時になりました。眠いです。。。

17
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
16