工厂中的依赖注入 [英] Dependency injection in factories

查看:179
本文介绍了工厂中的依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我真的是DI的新手,但是我真的想尝试使用它.

I'm really new to DI, but I really want to try using it.

有些事情我不理解.这是工厂的简单伪代码,我使用了很多.

There's something I don't understand. Here's a simple pseudocode of a factory, I'm using a lot.

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;
       }
   }
}

它具有非常简单的逻辑,它根据字符串选择实现实例.这非常有用,因为稍后我可以选择所需的页面,并且只会创建该页面.

It has a really simple logic, it chooses the implementation instance based on a string. It's very useful, because I can choose at a later time what page I need, and only that one will be created.

我将如何重写此代码,这样我的页面实例将由依赖项容器创建,因此不需要处理工厂及其创建的页面的依赖项?

我看到的唯一解决方案是使要使用的容器成为工厂的依赖项,并从工厂内部对其进行调用.我对此有很多疑问.

The only solution I see is to make the container I want to use, a dependency for the factory, and make calls to it from within the factory. I have lot's of problem with that.

首先,我不想将容器及其所拥有的每个工厂都耦合到我的应用程序中.

First, I don't want to couple the container into my application, and every factory it has.

第二,我最大的问题是,对容器的调用确实很乱,它是字符串输入的(即 $ container-> get('Foo'); ).我想尽可能少地使用它.如果可能的话,只有一次.

Second, and my biggest problem is, that the call for the container is really messy, it's stringly typed (i.e. $container->get('Foo');). I would like to use it as few times as possible. Only once if possible.

我不想写一个DI容器.我想使用一个现有的.我的问题是用法.在保持实例选择逻辑不变的同时,如何在上面的工厂内或在上面使用DI容器.

I do not want to write a DI container. I want to use an existing one. My question is on usage. How would I use a DI container instead or within the above factory, while keeping the logic on instance selection.

我开始使用骰子作为DI容器,因为它是轻量级的,并且知道我需要的一切.我希望可以在单个地方使用它并构建整个应用程序.为此,我需要一种方法以某种方式摆脱这些工厂,或者以某种方式对其进行修改,以使这些页面的行为像依赖项,因此DI容器将为其提供实例.

I started using Dice as the DI container, because it's lightweight, and knows everything I need. I would prefer if I could use it in a single place and build up the whole application. For that, I'll need a way to get rid of these factories somehow, or modify it in some way to make those pages behave like dependencies, so the DI container would provide instances to them.

是的,出于测试目的,我需要使用它.我也是测试的新手,但到目前为止,它真的很棒,我真的很喜欢.

Yes, I need this for testing purposes. I'm also new to testing, but it is very awesome so far, I really like it.

这些页面是MVC框架称为控制器的页面.但是我检出的所有MVC框架都不能使它们的控制器可测试,因为它们会自动创建它们的实例.并且由于它们是由系统创建的,因此它们的构造函数参数无法由用户自定义.

These pages are what MVC frameworks call controllers. But all the MVC frameworks I checked out are not making their controllers testable, because they create instances of them automatically. And because they are created by the system, their constructor parameters are not customizable by the user.

有一个简单的方法可以检查任何框架.我只是查找在该特定框架中的控制器中使用数据库的方式.大多数框架要么是过程性的,要么使用某种服务定位器,无论哪种方式,它们都是从公共作用域中获取其依赖项,这是我不想做的事情.这就是为什么我不自动化控制器实例化的原因.缺点是我现在有这些奇怪的工厂,这些工厂带有很多依赖项.而且我想将此任务替换为DI容器.

There is a simple way to check this for any framework. I just look up the way I should use a database in a controller in that specific framework. Most frameworks are either procedural, or use some service locator, either way, they are getting their dependencies from public scope, something I do not want to do. This is why I'm not automating the controller instantiation. The downside is that I now have these weird factories, which carry a lot of dependencies. And I would like to substitute this task to a DI container.

大多数框架都实现了自己的测试机制,这更像是功能测试,而不是单元测试,但是我也不想这样做.

Most frameworks implement their own testing mechanism, which are more like functional testing, instead of unit testing, but I do not want to do that either.

推荐答案

注意:依赖注入是一种设计模式,而DI容器是库,它们通过利用依赖注入来生成实例...或者它们是卑鄙的服务定位符,表明某人正在销售作为最新的流行话题

Note: dependency injection is a design pattern, while DI containers are libraries, which produce instances by utilizing dependency injection ... or they are shitty service locators, that someone is selling as latest buzz-thing

正确实施的DI容器基本上是智能工厂".但是实施一项可能会超出您当前的能力.这真的很复杂,因为一个好的DI容器构建整个依赖关系树.

A properly implemented DI container is basically a "smart factory". But implementing one will probably be way beyond your current capabilities. It's kinda really complicated, because a good DI container will build the whole dependency tree.

假设您有一个类Foo,它需要在构造中传递的AlphaBeta实例.但是有一个问题. Beta的实例在构造函数中还需要一个PDO DSN和一个Cache的实例.

Let's say you have a class Foo which needs instances of Alpha and Beta passed in construct. But there is an issue. Instance of Beta also needs in constructor a PDO DSN and an instance of Cache.

一个精良的DI容器将能够立即构造整个依赖关系树.

您应该使用现有的DI容器来代替自己做.

Instead of making one yourself, you should go with already existing DI container.

我的建议是 Auryn .

My recommendation would be Auryn.

这篇关于工厂中的依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆