当我使用 OO 设计模式时,我想确保我真的得到了它。我了解依赖注入的重要性以及服务容器/工厂对象。我喜欢工厂方法的想法,它可以在通过静态方法加载时将依赖项注入自身,返回完整的自身副本。我喜欢使用对象的代码中的干净程度。而且,在测试中,您可以注入不同的对象(覆盖或实例化而不使用工厂方法,见下文)
以下代码有什么引起警钟的吗?我是否正确理解这一点?
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');