【PHPデザインパターン】02_Singleton~いくつ作るかを制限する
引用記事
この記事を書くきっかけになったブログです。
記事内の解説やソースコードは、こちらのブログと著者の公開リポジトリを参考にしています。
Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Singleton~いくつ作るかを制限する
概要
- インスタンスを1つしか生成したくない場合に、生成するオブジェクトの数を1つに制限する。
- インスタンスへのアクセスを制限する。
構成
処理の流れ
処理の流れ
Singletonパターン
はSingletonクラス
によるインスタンスの生成が保証されています。
逆に、他クラスからインスタンスを生成できないように、Singletonクラス内で制限をかけます。
- 他クラスからインスタンスを作成できないように、Singletonクラスのコンストラクタを
private
で宣言する。 - 自分自身のインスタンス(Singletonインスタンス)を保持するための
static変数
を内部に持っている。 - ただひとつのインスタンスを返す
getInstanceメソッド
をstaticで宣言する。 - クラスをインスタンス化できるのはgetInstanceメソッドだけに限定する。
- 他クラスからインスタンスを複製できないように、
cloneメソッド
が呼ばれた場合は例外を返すようにする。
staticで宣言する理由
php.netからの引用です。
クラスプロパティもしくはメソッドをstaticとして宣言することで、クラスのインスタンス化の必要なしにアクセスすることができます。 staticなプロパティは、インスタンス化されたクラスオブジェクトからアクセスすることはできません (staticなメソッドにはアクセスできます)。
staticメソッド内では、矢印演算子(->)
や$this
が使用できないため、self
を使用してアクセスします。 今回はインスタンス化を行うメソッドと、そのインスタンスが格納されているプロパティに宣言されています。
staticで宣言されたメソッドやプロパティは、インスタンス化が行われていなくても外部から呼び出すことができます。クラス名::メソッド名()
のように記述します。これが外部からインスタンスを作成する唯一の方法になります。
さらにコンストラクタがprivateで宣言されているため、外部から勝手にnew
することもできません。
これらの記述により、インスタンスを作成するルートを制限しています。仮に複数のインスタンスを持ちたい場合は、Singletonクラスのメソッド自体を変更するしか方法はありません。
ソースコード
両ファイルは同じ階層に存在します。
<?php
namespace DoYouPhp\PhpDesignPattern\Singleton;
require dirname(__DIR__).'/vendor/autoload.php';
use DoYouPhp\PhpDesignPattern\Singleton\MySingletonSample;
// インスタンスを2回取得する
// getInstanceメソッドはstatic宣言がされているため、selfで呼び出している
$instance1 = MySingletonSample::getInstance();
// 2回めは既存のインスタンス($instance1)が返されているはず!
$instance2 = MySingletonSample::getInstance();
// 2つのインスタンスが同一IDかどうかを確認する
// getIDメソッドはstaticで宣言されていないため、矢印演算子が使用できる
if ($instance1->getID() === $instance2->getID()) {
echo '$instance1と$instance2は同一のIDです'."<br>"."\n";
} else {
echo '$instance1と$instance2は違うIDです'."<br>"."\n";
}
// 2つのインスタンスが同一かどうかを確認する
if ($instance1 === $instance2) {
echo '$instance1と$instance2は同一のインスタンスです'."<br>"."\n";
} else {
echo '$instance1と$instance2は違うインスタンスです'."<br>"."\n";
}
// cloneを試して複製できないことを確認する
try {
$instance1_clone = clone $instance1;
} catch (\RuntimeException $e) {
echo $e->getMessage()."<br>"."\n";
}
<?php
namespace DoYouPhp\PhpDesignPattern\Singleton;
class MySingletonSample {
// プロパティ(メンバ変数)の定義
private $id;
// インスタンスを保持する変数
private static $instance;
// コンストラクタ(オブジェクト生成時にコールされるメソッド)
// privateで宣言しているため、他のクラスから呼び出すことができない
// つまり、サブクラスを作成して呼び出すことはできない
// IDとして、現在のタイムスタンプと乱数の組み合わせからハッシュ値を作成する
private function __construct() {
$this->id = md5(time().mt_rand());
}
// 唯一のインスタンスを返すためのメソッド
// インスタンスが存在しない場合のみ、新規にインスタンスを作成する
// インスタンスが存在する場合は、既存のインスタンスを返す
// staticで宣言されているため、メソッド中で$thisを使用することができない
public static function getInstance() {
if (!isset(self::$instance)) {
self::$instance = new MySingletonSample();
echo get_class().'クラスでインスタンスを生成しました'."<br>"."\n";
} else {
echo '既に'.get_class().'クラスのインスタンスは存在します'."<br>"."\n";
}
return self::$instance;
}
// IDを返すメソッド
public function getID() {
return $this->id;
}
// インスタンスの複製を許可しないようにする
// finalキーワードで、サブクラスでメソッドを上書きできないようにする
// RuntimeExceptionは、実行時にだけ発生するようなエラーの際にスローされる
public final function __clone() {
throw new \RuntimeException(get_class($this).'クラスでは複数のインスタンスを生成することはできません'."<br>"."\n");
}
}
おまけ
use
でクラスをインポートすると、get_class関数
で取得するクラス名がDoYouPhp\PhpDesignPattern\Singleton\MySingletonSample
になるんですね。
require_once
でインポートした時は、MySingletonSample
だけでした。
Author And Source
この問題について(【PHPデザインパターン】02_Singleton~いくつ作るかを制限する), 我々は、より多くの情報をここで見つけました https://qiita.com/yukibe/items/4c51776584dbdd9fc7b3著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .