2009年にPHP 5.3が最初にリリースされてから2年目、このテンプレートを実装してきました。 当時、その前身であるバージョン5.2には遅延静的バインディングがなく、クラスのインスタンスを作成するために、その名前をメソッドに渡す必要がありましたが、これは私にとっては不自然に思えました。
PHP 5.4のリリースで、古い実装と言語の新しい機能をもう一度見て、このテンプレートを書き直しました-当時のように、そして今もそうであるように-最終バージョンです。
以下の実装の詳細。
私はすぐに主な機能に注意したいと思います:
- パラメトリック生成 。 :: getInstanceメソッド呼び出しのシグネチャを使用してクラスをインスタンス化できます。 各署名には、クラスの独自のインスタンスがあります。 デフォルトでは、このタイプの生成は無効になっています。 :: useParametricInstantiationメソッドをオーバーライドすることにより、子クラスに含まれます。
- 親クラスの名前で子を取得します。 名前を知らなくても、親および他のクラスから子クラスを参照できます。
- 親クラスの名前で子クラスを作成します 。 2番目の段落と同様に、子供が
*特性TSingleton。
*シングルトンデザインパターンの実装。
* /
名前空間特性;
/ **
*作成されたすべてのオブジェクトを保持するvar配列変数。
* /
$ objectPool = [];
特性TSingleton
{
/ **
* new演算子によるオブジェクトの作成を許可しないでください。
*
* 最終
*プライベートにアクセス
* voidを返す
* /
関数__construct(){}
/ **
*オブジェクトの複製を許可しません。
*
* 最終
*プライベートにアクセス
* voidを返す
* /
プライベート関数__clone(){}
/ **
*クラスがインスタンス化されるときに呼び出されます。
*
* アクセス保護
* voidを返す
* /
保護された関数onCreate(){}
/ **
*ユーザーレベルの初期化ルーチン。
*
* voidを返す
* /
保護された関数init(){}
/ **
*子クラスにマスクで指定された親がある場合、trueを返します。
*
* param string $ child
* param string $ parentMask
* 最終
* 静的
*公開アクセス
*ブール値を返す
* /
静的関数hasParentClass($子、$ parentMask)
{
$ currentClass = get_parent_class($ child);
if(!$ currentClass)
falseを返します。
する
{
if(strpos($ currentClass、$ parentMask)!== false)
trueを返します。
}
while($ currentClass = get_parent_class($ currentClass));
falseを返します。
}
/ **
*指定された親の「クラス名」を使用して、子クラスのインスタンスを返します
*マスクによって。 常に配列を返します。
*
* param string $ parentMask親の完全修飾クラス名のサブストリング。
* 最終
* 静的
*公開アクセス
*配列を返す | null
* /
静的関数getObjectByParent($ parentMask)
{
グローバル$ objectPool;
foreach($ objectPool as $ class => $ container)
if(self :: hasParentClass($ class、$ parentMask))
return array_values($コンテナー);
nullを返します。
}
/ **
*(その)親のクラス名のマスクでオブジェクトを検索します。 そうでない場合
*メソッドが作成することがわかりました。 常に配列を返します。
*
* param string $ parentMask
* param array $ initArgs
* 最終
* 静的
*公開アクセス
*配列を返す | null
* /
静的関数getObjectByParentSafe($ parentMask、$ initArgs = [])
{
$ child = self :: getObjectByParent($ parentMask);
if($ child!== null)
子$を返します。
//宣言されたすべてのクラスを検索します。
$ result = [];
foreach(get_declared_classes()として$クラス)
{
if(self :: hasParentClass($ class、$ parentMask))
{
$ result [] = call_user_func_array(($ class。 ':: getInstance')、$ initArgs);
}
}
戻りカウント($結果)? $結果:null;
}
/ **
*メソッドを呼び出した親クラスの子オブジェクトを返します。
*
* TSingleton :: getObjectByParentを参照
* 最終
* 静的
*公開アクセス
*配列を返す | null
* /
静的関数getMyChild()
{
return self :: getObjectByParent(get_called_class());
}
/ **
*安全な:: getMyChild。
*
* TSingleton :: getObjectByParentSafeを参照
* 最終
* 静的
*公開アクセス
*配列を返す
* /
静的関数getMyChildSafe()
{
$ initArgs = func_get_args();
return self :: getObjectByParent(get_called_class()、$ initArgs);
}
/ **
*クラスインスタンスを返します。
*
* 静的
* 最終
*公開アクセス
* TSingletonを返す
* /
静的関数getInstance()
{
グローバル$ objectPool;
$ argsArray = func_get_args();
$ class = get_called_class();
if(static :: useParametricInstantiation()&& count($ argsArray))
{
$指紋= '';
foreach($ argsArrayとして$ arg)
$フィンガープリント=シリアライズ($ arg);
$ key = md5($クラス。$指紋);
}
else //クラス名をキーとして使用します。
$ key = $ class;
if(!isset($ objectPool [$ class]))
$ objectPool [$クラス] = []; // Initクラスオブジェクトコンテナ。
if(isset($ objectPool [$ class] [$ key]))
return $ objectPool [$クラス] [$キー];
$ instance = new $ class();
//インスタンスをオブジェクトプールに追加します。
$ objectPool [$クラス] [$キー] = $インスタンス;
call_user_func_array([$インスタンス、 'onCreate']、$ argsArray);
$ instance-> init();
$インスタンスを返します。
}
/ **
*パラメトリッククラスのインスタンス化を有効または無効にします。 デフォルトでは無効になっています。
*
*公開アクセス
* 静的
*ブール値を返す
* /
静的関数useParametricInstantiation()
{
falseを返します。
}
}
:
作成されたすべてのオブジェクトは、1つの変数に保存されます。 この変数の範囲は(作業質量の要求に応じて)不純物によって制限されます。
非標準パターンでパターンを引き裂かないようにするために、パラメトリック生成のあるシングルトンはマルチトンと呼ばれるようになりました。