PHPでGoFデザインパターン 02 Singleton

Singletonパターンって?

Wikipediaによると

そのクラスのインスタンスが1つしか生成されないことを保証することができる。 ロケールやLook&Feelなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される。

唯一のインスタンスとそれにアクセスするための方法もあわせて提供される。
グローバル変数みたいなもの?

Cloneされた場合の対応

Clone対策が必要になる模様・・後日調査する
→続き:PHPでGoFデザインパターン 02 Singleton (その2:Clone対策)

分類

生成に関するパターン

パターンの例

パターンの構造

SingletonパターンにはSingletonクラスしかない。
コンストラクタをprivateにし、他のクラスから直接インスタンスを生成できないようにしている。
呼び出しは自分自身のインスタンスを生成するstaticなメソッドがある。
自分自身のインスタンスをstatic変数に保持する。

Singletonパターンを使うメリット

自分自身のインスタンスを内部に持ち、そのインスタンスへのアクセス方法も限られているので
他のクラスからのアクセスも制御できることになる。

3つまで生成可能、とか。

Singletonパターンを使うデメリット

Singletonパターンの使いどころ

プログラム内で
(良い) インスタンスを1つしか作らない   → Singleton使おう
(悪い) インスタンスを複数作られると困る → Singleton使おう

Singletonパターンのsample

インスタンスが複数生成されているかを区別するために、privateな変数$dataを持ち、コンストラクタ内で乱数をセットする。
複数回インスタンスを生成し、変数の値が同じであれば同一インスタンスと判断する。

SingletonSample.php

<?php
namespace GofStudy\Singleton;

/**
 * SingletonSample
 *
 * @version $id$
 * @author keynodes <keynodes@gmail.com>
 */
class SingletonSample
{
    /**
     * data
     *
     * @var mixed
     * @access private
     */
    private $data;

    /**
     * instance
     *
     * @var mixed
     * @access private
     */
    private static $instance;

    /**
     * __construct
     *
     * @access private
     * @return void
     */
    private function __construct()
    {
        // インスタンスが生成されるたびに乱数を発生させる
        $this->data = mt_rand();
    }

    /**
     * getData
     *
     * @access public
     * @return void
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * getInstance
     *
     * @static
     * @access public
     * @return void
     */
    public static function getInstance()
    {
        // new してないのでself::でアクセス
        if(!isset(self::$instance)) {
            // インスタンスがなければ生成する
            self::$instance = new SingletonSample();
            echo "instance created\r\n";
        } else {
            echo "instance already created\r\n";
        }

        return self::$instance;
    }
}

続いてクライアント側のコード。

直接インスタンス生成できないよう、SingletonSample のコンストラクタはprivaeで実装しているので、newしようとするとエラーが発生する。

Call to private SingletonSample::__construct() from invalid context

ダブルコロン(::)でメソッドを直接呼び出している。

SingletonClient.php

<?php

require_once 'SingletonSample.php';

$instance1 = GofStudy\Singleton\SingletonSample::getInstance();
sleep(1);
$instance2 = GofStudy\Singleton\SingletonSample::getInstance();


echo "=====instance1=====\r\n";
echo "data:[" . $instance1->getData() . "]\r\n";

echo "=====instance2=====\r\n";
echo "data:[" . $instance2->getData() . "]\r\n";

クラス図

あとで作る

実行結果

php CloneableSingletonClient.php
instance created
instance already created

instance1:[832348161] 
instance2:[832348161] ←同じ値(2回目はインスタンスが生成されていない)

Singletonパターンに関連するパターン