オブジェクト指向の設計パターンを使用しているので、本当に理解しているかを確認したいと思います。依存性注入の重要性と、サービス コンテナー/ファクトリ オブジェクトについても理解しています。静的メソッドを介してロードされたときに依存関係を自分自身に注入し、完全な自分自身のコピーを返すことができるファクトリ メソッドのアイデアが気に入っています。オブジェクトを消費するコードがすっきりしていて気に入っています。また、テストでは、代わりに別のオブジェクトを注入できます (ファクトリ メソッドを使用せずに上書きまたはインスタンス化します。以下を参照)。
次のコードについて警鐘を鳴らすものはありますか? 私はこれを正しく理解していますか?
abstract class AbstractClass
{
public function __construct ()
{
}
public static function factory ()
{
throw new Exception ('Please create a concrete class version of the method ' . __FUNCTION__);
}
public function inject ($class, $className=null)
{
if ($className === null)
{
$className = get_class ($class);
}
$this->{$className} = $class;
}
}
class ConcreteClass extends AbstractClass
{
public static function factory ()
{
$me = new self;
$me->inject (RebarClass::factory ());
$me->inject (AsphaltClass::factory ());
$me->inject (CementClass::factory ());
return $me;
}
public function doSomething ()
{
echo $this->RebarClass->doSomethingCool ();
}
}
class RebarClass extends AbstractClass
{
public static function factory ()
{
return new self;
}
public function doSomethingCool ()
{
return "I did something, but it wasn't that cool...\n";
}
}
class AsphaltClass extends AbstractClass
{
public static function factory ()
{
return new self;
}
}
class CementClass extends AbstractClass
{
public static function factory ()
{
$me = new self;
$me->inject (AsphaltClass::factory ());
$me->inject (SandClass::factory ());
return $me;
}
}
class SandClass extends AbstractClass
{
public static function factory ()
{
return new self;
}
}
私にとって、これにより、コントローラーやその他のモデルでオブジェクトを作成および使用するときに多くの柔軟性が得られます。次のようにインスタンス化できます。
$concreteClass = ConcreteClass::factory ();
そして今、私のオブジェクトは私が望むように設定されています
print_r ($concreteClass);
echo "\n";
出力:
ConcreteClass Object
(
[RebarClass] => RebarClass Object
(
)
[AsphaltClass] => AsphaltClass Object
(
)
[CementClass] => CementClass Object
(
[AsphaltClass] => AsphaltClass Object
(
)
[SandClass] => SandClass Object
(
)
)
)
そして、内部的に他のオブジェクトは使いやすいです
echo $concreteClass->doSomething ();
これを単体テストに使用する場合は、次のいずれかを実行できます。
$concreteClass = ConcreteClass::factory ();
$concreteClass->inject(new DifferentAsphaltClass, 'AsphaltClass'); // overwrite
また
$concreteClass = new ConcreteClass; // now you are responsible for setting up dependencies yourself
$concreteClass->inject (new YetAnotherAsphaltClass, 'AsphaltClass');