2013-07-23 251 views
3

首先,对不起我的英文不好,我希望你明白我在说什么。依赖注入和依赖不使用

这是我的问题:

让我们假设我有一个MVC应用包括标准路由器,控制器,模型(服务)层和某种分贝连接器。
模型层依赖于数据库连接器,控制器依赖于模型/服务,顶级“应用程序”类取决于路由器和控制器。
我的对象层次结构是这样的:

App -> ControllerFactory -> ServiceFactory -> DAO -> DbConnection

也许,上面写的并不像最好的应用架构不断,但我希望把重点放在其他的事情:
当我试图实例化一个App类,我应该将所有的依赖关系传递给实例化的类;类依赖关系依次具有自己的依赖关系等等。
因此,我得到所有层次堆栈立即实例化。但是如果我在某些情况下不需要访问数据库呢?如果某些控制器用于渲染静态模板而没有模型交互?
我的意思是,如果在某些特殊情况下类不需要自己的依赖关系(并且在某些情况下它可以)呢?我应该有条件地注入依赖吗?
我真的被困在这一点,我不知道该怎么办。

回答

3

更新:重新仔细阅读您的问题后,这里是另一个建议:是的,每个类都有不同的依赖关系。

不要将每个对象注入每个其他对象。例如,一些服务可能需要DAO,所以注入它们。但是如果服务不需要DAO,请不要注入任何DAO。

我的答案的其余部分是有效的,如果你有(例如)需要一个DAO(因此一个数据库连接)服务不是每个方法。


你可能会找什么是懒注射

这是注入依赖关系未加载的行为,以便该对象仅在使用/加载时加载。

以对照术语来说,这意味着注入一个代理对象,它的外观和行为与原始对象(例如db连接)完全相同。

几个DI容器(框架)支持这个,所以你不必自己创建代理。我将以PHP-DI为例(我从事该项目的参与工作)。

下面是使用上的注释的例子:

use DI\Annotation\Inject; 

class Example { 
    /** 
    * @Inject(lazy=true) 
    * @var My\Class 
    */ 
    protected $property; 

    /** 
    * @Inject({ "param1" = {"lazy"=true} }) 
    */ 
    public function method(My\Class $param1) { 
    } 
} 

当然,如果你不想使用注释,你可以使用任何你想要(PHP,YAML,...)任何其他配置。这里是相同的例如通过在纯PHP配置容器:

$container->set('Example') 
    ->withProperty('property', 'My\Class', true) 
    ->withMethod('method', array('param1' => array(
      'name' => 'My\Class', 
      'lazy' => true, 
     ))); 

其他位于the documentation about Lazy Injection


注意:您可能不被使用的容器,现在(这不是一个问题),但对于解决延迟注入,这是工作了相当数量的,你可能需要开始使用一个考虑。

+0

使用代理是一个非常好的主意,我会试试看,谢谢! –

0

如果您的依赖关系构造比较复杂,只需添加一个新的工厂类,该工厂类应包含所有逻辑以为您创建正确的对象。

class AppFactory(){ 

    __construct(all params){ 

    } 
    build(useDB=true){ 
     // logic to build 
     if(useDB){ 
      App = new App(new ControllerFactory(new ServiceFactory(new DAO(new DbConnection(params))))) 
     } else { 
      App = new App(new ControllerFactory(new ServiceFactory(null)))) 
     } 

     return App; 
    } 
}