未使用依赖项注入和依赖项



首先,很抱歉我的英语不好,我希望你能理解我的意思。

这是我的问题:

假设我有一个MVC应用程序,包括标准路由器、控制器、模型(服务)层和某种数据库连接器
模型层依赖于数据库连接器,控制器依赖于模型/服务,顶级"应用程序"类依赖于路由器和控制器
我的对象层次结构如下:

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

也许,上面写的并不是有史以来最好的应用程序体系结构,但我想关注另一件事:
当我试图实例化一个应用程序类时,我应该将所有依赖项传递给实例化的类;类依赖关系反过来又有自己的依赖关系等等。
因此,我一次实例化了所有层次结构堆栈。但是,如果在某些情况下我不需要访问数据库,该怎么办;如果一些控制器用于在没有模型交互的情况下渲染静态模板,该怎么办
我的意思是,若类不需要它自己的依赖关系(在某些情况下它需要依赖关系),那个么会发生什么情况呢?我应该有条件地注入依赖项吗
我真的陷入了困境,不知道该怎么办。

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

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

如果(例如)有一个服务需要DAO(从而需要DB连接),而不是每个方法,那么我的其余回答都是有效的。


您可能正在寻找惰性注入

它是注入未加载的依赖项的行为,因此只有在使用时才加载对象。

在conrete术语中,这意味着注入一个代理对象,该对象看起来和行为都与原始对象(例如,数据库连接)完全相同。

有几个DI容器(框架)支持这一点,因此您不必自己创建代理。我将以PHP-DI为例(仅供参考,我从事该项目)。

下面是一个使用注释的示例:

use DIAnnotationInject;
class Example {
    /**
     * @Inject(lazy=true)
     * @var MyClass
     */
    protected $property;
    /**
     * @Inject({ "param1" = {"lazy"=true} })
     */
    public function method(MyClass $param1) {
    }
}

当然,如果你不想使用注释,你可以使用任何其他你想要的配置(PHP,YAML,…)。以下是用纯PHP配置容器的相同示例:

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

请参阅有关Lazy Injection的文档中的更多信息。


注意:您现在可能还没有使用Container(这不是问题),但要解决延迟注入问题,这是一项相当大的工作,您可能需要开始考虑使用Container。

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

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

最新更新