PHPでGoFデザインパターン 02 Singleton (その2:Clone対策)

前回PHPでGoFデザインパターン 02 Singletonの続き。
今回はオブジェクトのCloneを作成した場合のはなし。

オブジェクトをCloneした場合

元オブジェクトとクローンしてできたオブジェクトの比較をするために
乱数をセットするメソッドを追加し、呼び出して結果を見る。

Singletonクラス側

     public function setRandData()
     {
         $this->data = mt_rand();
     }

クライアント側

// クローンの作成
$instance1_clone = clone $instance1;

// それぞれのオブジェクトを操作する
echo "=====setRandData=====\r\n";
$instance1->setRandData();
$instance1_clone->setRandData();

// 結果を比較
echo "instance1      :[" . $instance1->getData() . "]\r\n";
echo "instance1_clone:[" . $instance1_clone->getData() . "]\r\n";

結果

つまり、Singletonの特徴である

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

(Wikipediaより引用)
が実現できていないことになる。

Clone対策

http://php.net/manual/ja/language.oop5.cloning.phpによると

オブジェクトのコピーは、clone キーワード (これは、そのオブジェクトの __clone() メソッドがある場合にこれをコールします)により作成されます。 オブジェクトの __clone() メソッドを直接コールすることはできません。

__clone()メソッドを追加し、その内で例外を発生させてみる。

SingletonSample.php

     public final function __clone()
     {
         throw new RuntimeException ('Clone is not allowed class:'. get_class($this));
     }

実行結果