絶版されているけれど、Google booksで公開されているのが見れます。
https://books.google.co.jp/books?id=sXNh4TeQeBIC&printsec=frontcover&hl=ja#v=onepage&q&f=false
1日1パターンってことで演習してアウトプットしていきます。
もくじ
使いどころ
どうしてもインスタンスを1つしか生成したくない。
- システムの設定を表現するクラス
- システム全体で一度読み込んだデータをキャッシュしておく
- PDO接続など1回作成したインスタンスで使いまわせば良い場合
毎回DB利用のたびにPDOインスタンスを作成するのはコストがかかる - Setterがないクラス
- 全体の設定値などの一括管理
config
実装のポイント
/** * 唯一のインスタンスを保持する変数 */ private static $instance; /** * コンストラクタ * IDとして、生成日時のハッシュ値を作成 */ private function __construct() /** * * clone()の禁止 */ public final function __clone() { throw new RuntimeException('Clone is not allowed against' . get_class($this)); }
privateで指定している。
- private function __construct()
クラス内部からしかコンストラクタを実行できないようにしている - private static $instance
static変数は一回目に呼び出された時のみに初期化され、その後にスコープが移行しても値が初期化されず保持される。 - Singletonパターンを使う場合の注意 cloneを防止すること
/** * このインスタンスの複製を許可しないようにする * @throws RuntimeException */ public final function __clone() { throw new RuntimeException('Clone is not allowed against' . get_class($this)); }
- インスタンスの複製を防止している。
__cloneメソッドをオーバーライドし、例外を発生させて強制終了させる。
Singletonパターンのメリット
Singletonパターンを利用することで、クラスに対してインスタンスが1つしかないことを保証する。
それにアクセスするためのグローバルな方法を提供する。
SingletonSample.class.php
<?php class SingletonSample { /** * メンバー変数 */ private $id; /** * 唯一のインスタンスを保持する変数 */ private static $instance; /** * コンストラクタ * IDとして、生成日時のハッシュ値を作成 */ private function __construct() { $this->id = md5( date('r') . mt_rand() ); } /** * 唯一のインスタンスを返すためのメソッド * @return SingletonSample インスタンス */ public static function getInstance() { if(!isset(self::$instance)) { self::$instance = new SingletonSample(); echo 'a SingletonSample instance was created !'; } return self::$instance; } /** * IDを返す * @return インスタンスのID */ public function getId() { return $this->id; } /** * このインスタンスの複製を許可しないようにする * @throws RuntimeException */ public final function __clone() { throw new RuntimeException('Clone is not allowed against' . get_class($this)); } }
index.php
<?php require_once 'SingletonSample.class.php'; ini_set( 'display_errors', 1 ); /** * インスタンスを2つ取得する */ $instance1 = SingletonSample::getInstance(); sleep(1); $instance2 = SingletonSample::getInstance(); echo '<hr/>'; /** * 2つのインスタンスが同一IDかどうかを確認する */ echo 'instance ID : ' . $instance1->getId() . '<br/>'; echo '$instance1->getId() === $instance2->getId() : ' . ($instance1->getId() === $instance2->getId()? 'ture' : 'false'); echo '<hr/>'; /** * 複製できないことを確認 */ $instance1_clone = clone $instance1;
/demo/Design-Pattern-Primer-by-PHP/Singleton
@see