我对 DI 很陌生,但我真的很想尝试使用它。
有件事我不明白。这是一个简单的工厂伪代码,我经常使用。
class PageFactory {
public function __construct(/* dependency list */) {
... //save reference to the dependencies
}
public function createPage($pagename) {
switch ($pagename) {
case HomePage::name:
return new HomePage(/* dependency list */);
case ContactPage::name:
return new ContactPage(/* dependency list */);
...
default:
return null;
}
}
}
它有一个非常简单的逻辑,它根据字符串选择实现实例。它非常有用,因为我可以稍后选择我需要的页面,并且只会创建该页面。
我将如何重写此代码,以便我的页面实例将由依赖项容器创建,这样我就不需要处理工厂及其创建的页面的依赖项?
我看到的唯一解决方案是使我想要使用的容器成为工厂的依赖项,并从工厂内部调用它。我对此有很多问题。
首先,我不想将容器耦合到我的应用程序及其拥有的每个工厂中。
其次,我最大的问题是,对容器的调用确实很混乱,它是字符串类型的(即$容器->获取('Foo');)。我想尽可能少地使用它。如果可能的话,只进行一次。
EDIT:
我不想写一个 DI 容器。我想使用现有的。我的问题是关于使用情况。我将如何使用 DI 容器来代替或在上述工厂中使用,同时保留实例选择的逻辑。
EDIT 2:
我开始使用Dice https://r.je/dice.html作为 DI 容器,因为它是轻量级的,并且知道我需要的一切。我更希望能够在一个地方使用它并构建整个应用程序。为此,我需要一种方法来以某种方式摆脱这些工厂,或者以某种方式修改它,使这些页面表现得像依赖项,这样 DI 容器就会向它们提供实例。
EDIT 3:
是的,我需要这个用于测试目的。我也是测试新手,但到目前为止它非常棒,我真的很喜欢它。
这些页面就是 MVC 框架所称的控制器。但我检查的所有 MVC 框架都没有使其控制器可测试,因为它们会自动创建控制器的实例。并且因为它们是由系统创建的,所以它们的构造函数参数不能由用户自定义。
对于任何框架都有一个简单的方法来检查这一点。我只是查找在特定框架中的控制器中应该使用数据库的方式。大多数框架要么是程序性的,要么使用某种服务定位器,无论哪种方式,它们都会从公共范围获取依赖项,这是我不想做的事情。这就是为什么我没有自动化控制器实例化。缺点是我现在有这些奇怪的工厂,它们带有很多依赖项。我想将此任务替换为 DI 容器。
大多数框架都实现了自己的测试机制,这更像是功能测试,而不是单元测试,但我也不想这样做。