こんばんは。ファガイです。
本日はPHP5.4におけるシングルトンパターンの実装に関して書きたいと思います。
これを書こうと思ったのは自分がシングルトンパターンについて調べてた時に、「何かこの実装微妙だよね」とか、思った結果です。
最近書かれるブログでも、ちょっと書かれてる内容が古いな・・・って。ってことで書いてます。
PHP5.4以前のシングルトンパータンの実装に関しては、
絶版になったPHPによるデザインパターン入門のページを閲覧すると良いかと思います。
PHPによるデザインパターン入門
実を言うと、先日書きました、
ReflectionClassについて調べる – 新人Webエンジニアの記録。
が結構参考になりました。
PHP5.4におけるSingleton Pattern
こんな感じです。traitと、Reflection、遅延静的束縛を必要とします。
trait TraitSingleton
{
/**
* get instance.
*/
public static function getInstance() {
static $instance; // 静的なinstanceを保持するための変数
// インスタンスが存在しない時だけインスタンスを作る
if(! $instance)
{
// 遅延静的束縛
$reflection = new ReflectionClass(get_called_class());
$construct = $reflection->getConstructor();
$construct->setAccessible(true);
// インスタンスをコンストラクタ無しで作成
$instance = $reflection->newInstanceWithoutConstructor();
// コンストラクタを実行する
$construct->invokeArgs($instance ,func_get_args());
}
return $instance;
}
/**
* the instance clone is not allowd
* @throws RuntimeException
*/
public final function __clone()
{
throw new RuntimeException('Clone is not allowed against ' . get_called_class($this));
}
}
ちょっとした解説
あんまり必要ないかもですが・・・。
基本的にこのトレイトは以下のような使い方をします。
class Sample
{
use TraitSingleton;
private function __construct()
{
// コンストラクタ
}
}
$obj = Sample::getInstance();
はい。こんな感じ。
インスタンスをコンストラクタ無しで作る理由は、単にコンストラクタが実行出来ないためです。
privateなので。
コンストラクタだけをsetAccessibleでアクセス可能にして実行させることで、可能としています。
なお、フレームワーク等での実装だと一つ上にクラス等を被せてるので、publicでコンストラクタを書いてもシングルトンになってますね。
ではでは。
コメント