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回目はインスタンスが生成されていない)