Php 这种设计模式有没有一个名称(将您自己传递到您自己的依赖项中),这种技术的陷阱是什么?
我不盲目地遵循设计模式(我们真的只需要理解对象通信),但我也不想忽视它们 设计模式是否有一个名称(类似于或某种双重分派策略模式之类的东西),但不必重写每个方法和委派,只需将一个引用($this)传递给自己到依赖项中即可?这是程序员工具箱中的合理解决方案吗 需要一个实际的例子吗?当然……继续Php 这种设计模式有没有一个名称(将您自己传递到您自己的依赖项中),这种技术的陷阱是什么?,php,oop,design-patterns,delegation,Php,Oop,Design Patterns,Delegation,我不盲目地遵循设计模式(我们真的只需要理解对象通信),但我也不想忽视它们 设计模式是否有一个名称(类似于或某种双重分派策略模式之类的东西),但不必重写每个方法和委派,只需将一个引用($this)传递给自己到依赖项中即可?这是程序员工具箱中的合理解决方案吗 需要一个实际的例子吗?当然……继续 假设您使用的是DI容器,可能有一些控制器(MVC)方法如下: 图1: // Phew! Four dependencies injected here: public function index(Quer
假设您使用的是DI容器,可能有一些控制器(MVC)方法如下: 图1:
// Phew! Four dependencies injected here:
public function index(QueryManagerInterface $queryManager, BlogQueryInterface $blogQuery, RenderQueryPDFInterface $queryPDFRenderer, RequestInterface $request) {
// Do some "managing" of a query, then render it into a PDF
$queryManager->setQuery($query);
$queryManager->addInput($request->input());
$queryPDFRenderer->setQuery($query);
$output = $queryPDFRenderer->render();
return $output;
}
// Nice! Just two dependencies!
public function index(BlogQueryInterface $blogQuery, RequestInterface $request) {
$blogQuery->getQueryManager()->addInput($request->input());
$output = $blogQuery->getPDFRenderer()->render();
return $output;
}
现在,设想控制器方法如下所示:
图2:
// Phew! Four dependencies injected here:
public function index(QueryManagerInterface $queryManager, BlogQueryInterface $blogQuery, RenderQueryPDFInterface $queryPDFRenderer, RequestInterface $request) {
// Do some "managing" of a query, then render it into a PDF
$queryManager->setQuery($query);
$queryManager->addInput($request->input());
$queryPDFRenderer->setQuery($query);
$output = $queryPDFRenderer->render();
return $output;
}
// Nice! Just two dependencies!
public function index(BlogQueryInterface $blogQuery, RequestInterface $request) {
$blogQuery->getQueryManager()->addInput($request->input());
$output = $blogQuery->getPDFRenderer()->render();
return $output;
}
我是怎么做到的?所有这些类中的所有代码都是相同的,只是我更新了$blogQuery类:
Class BlogQuery Implements BlogQueryInterface, QueryManageableInterface, PDFRenderableInterface {
public function __construct(QueryManagerInterface $manager, $PDFRendererInterface $pdfRenderer){
// Here I pass a reference of this own class into its dependencies
$this->manager = $manager->setQuery($this);
$this->pdfRenderer = $pdfRenderer->setQuery($this);
}
public function getQueryManager() { return $this->manager; }
public function getPDFrenderer() { return $this->pdfRenderer; }
...
}
图2的优点是:
- 减少对控制器方法的依赖
- 更少的代码行
- 组合重于继承(更松散耦合?)
- 不需要像使用委托模式时那样“键入一堆重复的方法”
- 更容易理解。注入BlogQuery和请求似乎捕获了主上下文。(主观)
我在图2中使用了什么模式?这种方法的缺点是什么?这种方法被认为是良好的oop实践吗?在我看来,这就像是,
\uuu构造
使查询管理器界面
和PDFrenderInterface
成为博客查询
的访问者
我不想太多地涉及编程模式的利弊,因为在大多数情况下,它们都是有利的。但是,访问者模式的一个非常客观的结果是,与其他选项相比,它往往在文件/类之间有更多的跳跃,这使得读者更难将其加载到他们的大脑中。最终,“良好的OOP实践”归结为经验、判断,并可能重写三次
我想指出的是,您并没有真正减少
索引
函数的依赖性。是的,它需要更少的参数,但它仍然知道querymanagerface
和renderQueryPDInterface
的行为。如果这些接口发生更改(例如,重命名addInput
或render
),则索引中的代码也必须更改。在测试索引时,仍然需要设置或模拟这两个对象,才能通过测试。除非您可以将该行为隐藏在BlogQueryInterface
和RequestInterface
(另请参见)中,index
在这两种方法中具有完全相同的依赖关系。我也不会盲目地遵循设计模式,但当其他人可以轻松理解您所做的工作时,它确实会有所帮助。我认为,如果大家都了解并使用类似的方法,那么它在工作流方面会更有帮助。如果这真的有名字,我会很感兴趣的,问得好!我认为第二个例子比第一个更糟糕,BlogQuery不应该了解PDFrenderer。我觉得控制器有几个依赖项并不奇怪。