我很新于依赖注入,但我真的想尝试使用它。
有一些我不理解的地方。以下是我经常使用的工厂的简单伪代码。
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;
}
}
}
这个逻辑非常简单,它根据一个字符串来选择实现实例。这非常有用,因为我可以在稍后的时间内选择我需要的页面,并且只会创建那个页面。
我该如何重写这段代码,以便我的页面实例将通过依赖容器创建,因此我就不需要处理工厂和其创建的页面的依赖关系了?
唯一的解决方案是使我想要使用的容器成为工厂的依赖项,并从工厂内部调用它。但我有很多问题。
首先,我不想将容器耦合到我的应用程序中,也不想将容器耦合到每个工厂中。
其次,而我最大的问题是,对于容器的调用非常混乱,它是以字符串形式(即$container->get('Foo');)存在的。我希望尽可能少地使用它。如果可能,只使用一次。
编辑:
我不想编写DI容器,我想使用现有的容器。我的问题是关于用法的。在上述工厂中,如何使用DI容器或将其嵌入其中,同时保持实例选择的逻辑。
编辑2:
我开始使用Dice作为DI容器,因为它很轻量级并且知道我需要的一切。我希望能在一个地方使用它并构建整个应用程序。为此,我需要一种方法来消除这些工厂,或以某种方式修改它们,使这些页面像依赖项一样运行,以便DI容器可以为它们提供实例。
编辑3:
是的,我需要这个用于测试目的。我还不熟悉测试,但到目前为止,它非常棒,我真的很喜欢。
这些页面是MVC框架所称的控制器。但我查看的所有MVC框架都没有使其控制器可测试性,因为它们自动创建它们的实例。由于它们是由系统创建的,用户无法定制它们的构造函数参数。
有一种简单的方法可以检查任何框架的情况。我只需查找在特定框架中应该如何在控制器中使用数据库的方式。大多数框架要么是过程化的,要么使用一些服务定位器,无论哪种方式,它们都从公共范围获取其依赖项,这是我不想做的。这就是为什么我没有自动化控制器实例化的原因。缺点是现在我有了这些奇怪的工厂,它们携带很多依赖项。我想将此任务代替DI容器。
大多数框架都实现了自己的测试机制,这更像是功能测试,而不是单元测试,但我也不想这样做。