Php 创建一个使用其他工厂来构建最终具体对象的工厂实现是否是一种良好的实践?
在我正在构建的应用程序中,有一个CLI入口点类:Php 创建一个使用其他工厂来构建最终具体对象的工厂实现是否是一种良好的实践?,php,design-patterns,dependency-injection,factory,Php,Design Patterns,Dependency Injection,Factory,在我正在构建的应用程序中,有一个CLI入口点类: class CLIEntryPoint { protected $factory; public function __construct(ApplicationObjectFactoryInterface $factory) { $this->factory = $factory; } public function run(...$args) { $choice = $args[1]
class CLIEntryPoint {
protected $factory;
public function __construct(ApplicationObjectFactoryInterface $factory) {
$this->factory = $factory;
}
public function run(...$args) {
$choice = $args[1];
$appObject = $this->factory->makeApplicationObject($choice);
$appObject->doApplicationRelatedStuff();
}
}
这个入口点是在我的“front controller”脚本中使用依赖项注入创建的,它接收一个ApplicationObjectFactoryInterface
实现(实际上,ApplicationObjectFactoryInterface
的当前实现是由DI容器注入的,DI容器反过来从其配置文件中读取它,但这不是重点)
ApplicationObjectFactoryInterface
的当前实现也使用DI,并且依赖于帮助其构建最终应用程序对象的其他工厂:
class CurrentImplementationOfApplicationObjectFactory implements ApplicationObjectFactoryInterface {
protected $someComponentFactory;
protected $anotherComponentFactory;
public function __construct(SomeComponentFactoryInterface $someComponentFactory, AnotherComponentFactoryInterface $anotherComponentFactory) {
$this->someComponentFactory = $someComponentFactory;
$this->anotherComponentFactory = $anotherComponentFactory;
}
/**
* Interface's method
*
* @return ApplicationObjectInterface
*/
public function makeApplicationObject($choice) {
$component = $this->someComponentFactory->makeSomeComponent();
$anotherComponent = $this->anotherComponent->makeAnotherComponent();
switch ($choice) {
case 1:
return new CurrentImplementationOfApplicationObject1($component, $anotherComponent);
case 2:
return new CurrentImplementationOfApplicationObject2($component, $anotherComponent);
default:
return new DefaultImplementationOfApplicationObject($component, $anotherComponent);
}
}
}
这里的CurrentImplementationOfApplicationObject1
,CurrentImplementationOfApplicationObject2
和DefaultImplementationOfApplicationObject
都实现了ApplicationObjectInterface
接口,因此它们都具有doApplicationRelatedStuff
方法
我想知道像我这样编写代码是否是一种好的做法,如果不是,我如何改进它
基本上,我在这里创建一个依赖于其他组件的组件,以便使用工厂正常工作,而工厂又需要内部工厂来构建实现ApplicationObjectInterface
接口的组件
这被认为是良好的做法吗
一如既往,感谢您的关注
编辑:我看了Steven的文章,试图重构CLIEntryPoint。现在唯一的问题似乎是如何将$choice
参数传递给工厂,当运行()时,工厂现在位于代理内部调用了
方法。此代码结构是否比我上面发布的代码结构好?当然,某些ComponentFactoryInterface
和另一个ComponentFactoryInterface应该遵循相同的行为(使用它们的工厂不应该直接使用它们,而是通过两个代理来实现,SomeComponentInterface
和另一个ComponentInterface
)。无论如何,我希望我做对了,下面是代码:
class CLIEntryPoint {
protected $applicationObject;
public function __construct(ApplicationObjectInterface $applicationObject) {
$this->applicationObject = $applicationObject;
}
public function run(...$args) {
$choice = $args[1]; // How do I deal with different choices when I am using a Proxy? I should have different application objects depending on input.
$this->applicationObject->doApplicationRelatedStuff();
}
}
interface ApplicationObjectInterface {
public function doApplicationRelatedStuff();
}
class ApplicationObjectProxy implements ApplicationObjectInterface {
protected $applicationObjectFactory;
protected $applicationObjectImplementation = NULL;
public function __construct(ApplicationObjectFactoryInterface $factory) {
$this->applicationObjectFactory = $factory;
}
public function __call($method, $args) {
// Calling interface's
$implementation = $this->getImplementation();
$methodOfInterfaceToCall = preg_replace('/Proxy$/', '', $method);
return $implementation->{$methodOfInterfaceToCall}(...$args);
}
/**
* Laxy loading method.
*/
protected function getImplementation() {
if (is_null($this->applicationObjectImplementation)) {
$this->applicationObjectImplementation = $this->applicationObjectFactory->makeApplicationObject(); // Choice should go here somehow...
}
return $this->applicationObjectImplementation;
}
public function doApplicationRelatedStuff() {
// This will call the PHP's magic `__call` method, which in turn will forward the call to the application object's
// implementation returned by the factory.
return $this->doApplicationRelatedStuffProxy();
}
}
事实上是的,这是一种称为抽象工厂模式的模式。因此,我在本科期间在全班同学面前展示了一个例子: 因此,如果您正在制作视频游戏第一人称射击游戏,您可能需要创建三个具体工厂,如:
因此,请更直接地回答您的描述,查看上面的代码,您询问了关于依赖项注入的选择问题。对于依赖项注入,我相信对于这种模式,您必须在代码尝试实现之前注入每个具体类班级 例如:
- 上面的代码说run方法给出了一个名为 选择
- 使用此选项,必须将其用作getImplementation方法的参数
- getImplementation方法依赖于依赖关系的所有具体对象 在调用getImplementation方法之前,必须先创建注入
- 但是,由于您不知道将调用哪个实现类,我相信您必须先注入所有实现类
- 然后,您可以使用选项变量作为参数来获得正确实现的factory类
希望这有帮助!您应该阅读。感谢您的洞察力!我希望我做对了。请检查我的编辑。我试图重构我的代码,以便
CLIEntryPoint
现在取决于应用程序对象的接口。然后有一个实现充当代理并将其调用转发到实际实现的调用,这是我从一个内部工厂获得的,它现在是代理的内部工厂,因此不是CLIEntryPoint
的依赖项。我现在的问题是初始的$choice
参数,我现在不知道如何传递到工厂,因为我已经将其移动到代理内部了……您能评论我的代码吗?