前提
先日はシングルトンのようで、ファクトリーパターンのような仕組みが必要になったのがきっかけです。
シングルトンの場合は、インスタンスが1度だけ生成されて、それ以降はStaticプロパティーを参照するのみですね。
ファクトリーパターンの場合は、インスタンスを生成し続ける目的で、場合によってはクラスの中で管理することもある。
その役割をミックスさせてパターンが必要になったので、備忘録代わりに書こうと思います。
1クラスにつき1インスタンスだけ生成させるパターン!
わかりにくいと思いますので、簡単なサンプルを載せいておきます。
abstract class Singleton
{
protected static $instance;
protected function __construct(){}
public static function get_instance()
{
if( static::$instance === null )
{
static::$instance = new static();
}
return static::$instance;
}
final function __clone()
{
throw new \Exception('Clone is not allowed against' . __CLASS__);
}
final function __wakeup()
{
throw new \Exception('Unserialize is not allowed against' . __CLASS__);
}
}
class A extends Singleton {}
class B extends Singleton {}
A::get_instance();
B::get_instance();
// 結果:両方ともAクラスのインスタンスを返す
当然、両方のインスタンスはAクラスのものになります。これはシングルトンの正常動作ですね。
しかし、今回は1クラスにつき1つまでのインスタンスを生成したいので、下記のように変更します。
abstract class Singleton_Factory
{
protected static $instances = array();
protected function __construct(){}
public static function get_instance()
{
$called_cl = get_called_class();
if( ! isset(static::$instances[ $called_cl ]) )
{
static::$instances[ $called_cl ] = new static();
}
return static::$instances[ $called_cl ];
}
final function __clone()
{
throw new \Exception('Clone is not allowed against' . __CLASS__);
}
final function __wakeup()
{
throw new \Exception('Unserialize is not allowed against' . __CLASS__);
}
}
各クラスのインスタンスをStaticプロパティーで管理して、1つ以上は作らせない仕組みですね。
そもそもインスタンスを1つに制限させる理由は、使用するメモリを減らすことと、不具合を防ぐためですね。
Wordpressを例にすると、下記のようなコードをプラグインでよく見かけます。
class Sample_Plugin
{
public function __construct()
{
add_action("init", array(&$this, "init"));
}
public function init()
{
echo "do something here";
}
}
new Sample_Plugin();
よく考えると、このクラスは1度しか初期化されちゃいけないんですよね。
なぜなら、initフックが二重で登録され、initメソッドが複数回呼ばれてしまうからです。
プラグインの中であれば製作者だけの問題なのですが、配布するとなれば気をつけた方がいい気がします。
以上、使い道は少なそうですが、備忘録用に載せておきます。