PHPは一例モードで一番安全なやり方を実現します。
一般的な設計モードとしては、一例モードが広く使用されている。どのように一つの例を設計するのが一番いいですか?
私達は通常このように書きます。ネットで検索できる例も大部分がそうです。constructメソッドをプライベートに設定すると、このクラスは他の人に実装されないことが保証されます。しかし、この書き方で明らかな問題は、コードが多重化されないことである。例えば、クラスA:
注意したいのは、PHPのシングルモデルはJavaのようなスレッドセキュリティの問題はないが、状態のあるクラスについては、単一の例モードを注意して使用することです。単例モードのクラスはPHP動作のライフサイクル全体を伴い、メモリに対してもオーバーヘッドとなります。
私達は通常このように書きます。ネットで検索できる例も大部分がそうです。constructメソッドをプライベートに設定すると、このクラスは他の人に実装されないことが保証されます。しかし、この書き方で明らかな問題は、コードが多重化されないことである。例えば、クラスA:
class A
{
protected static $_instance = null;
protected function __construct()
{
//disallow new instance
}
protected function __clone(){
//disallow clone
}
public function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new self();
}
return self::$_instance;
}
}
class B extends A
{
protected static $_instance = null;
}
$a = A::getInstance();
$b = B::getInstance();
var_dump($a === $b);
上のコードは出力されます。
class B extends A
{
protected static $_instance = null;
}
$a = A::getInstance();
$b = B::getInstance();
var_dump($a === $b);
問題はselfにあります。selfの引用はクラスが定義された時に決定されます。つまり、BのAを継承しています。彼のselfの引用は依然としてAを指しています。この問題を解決するために,PHP 5.3に後期静的バインディングの特性を導入した。簡単に言えば、staticキーワードで静的な方法や変数にアクセスすることで、selfとは違って、staticの引用は運転時に決定されます。そこで私たちのコードを簡単に書き換えて、一例のモードを多重化できるようにします。
bool(true)
以上のコード出力:
class C
{
protected static $_instance = null;
protected function __construct()
{
}
protected function __clone()
{
//disallow clone
}
public function getInstance()
{
if (static::$_instance === null) {
static::$_instance = new static;
}
return static::$_instance;
}
}
class D extends C
{
protected static $_instance = null;
}
$c = C::getInstance();
$d = D::getInstance();
var_dump($c === $d);
このようにして、簡単な継承と初期化を行います。instance変数は単例モードを実現できます。上の方法はPHP 5.3でしか使えませんので、前のバージョンのPHPに対しては、正直に各タイプにget Instanceを書いてください。注意したいのは、PHPのシングルモデルはJavaのようなスレッドセキュリティの問題はないが、状態のあるクラスについては、単一の例モードを注意して使用することです。単例モードのクラスはPHP動作のライフサイクル全体を伴い、メモリに対してもオーバーヘッドとなります。