简体   繁体   English

依赖注入容器与注册表模式

[英]Dependency Injection Container vs Registry pattern

I understand that the Dependency Injection principle is all about decoupling code. 我知道依赖注入原则就是解耦代码。 Instead of making new instances in the classes, instead you inject them, which make them loosely coupled. 而不是在类中创建实例,而是注入它们,这使它们松散耦合。

Now if I have to pass on a set of objects that will be used through several classes throughout my application, I can make a container (commonly called dependency injection container). 现在如果我必须传递一组将在我的应用程序中通过几个类使用的对象,我可以创建一个容器(通常称为依赖注入容器)。

That is exactly what i am doing because I have to pass a config object, a logger object, a translator object, etc. which will be used through several classes instances of my application. 这正是我正在做的事情因为我必须传递一个配置对象,一个记录器对象,一个翻译器对象等,它将通过我的应用程序的几个类实例使用。 I am passing the whole container through several classes, even if not all of the classes need access to all the objects within the container. 我将整个容器传递给几个类,即使并非所有类都需要访问容器中的所有对象。 This led me to the following question: what is the difference if I create a global Registry and put the objects in there, then retrieve them like Registry::getInstance()->get('logger'); 这引出了以下问题:如果我创建一个全局注册表并将对象放在那里,然后像Registry :: getInstance() - > get('logger')那样检索它们,有什么区别? ? Wether I use a global registry or a dependency container, class isntances will have access to all the objects within the container or registry, even if they don't need to see/access all of them. 我使用全局注册表或依赖容器,类isntances可以访问容器或注册表中的所有对象,即使他们不需要查看/访问所有对象。

Conclusion: What is the difference if I pass a dependency injection container along my classes or a global Registry ? 结论:如果我沿着类或全局注册表传递依赖注入容器,有什么区别?

Note: sometimes people use Registries by different names. 注意:有时人们使用不同名称的注册表。 The common ones that i have seen as: Locator, Context and System. 我看到的常见的:定位器,上下文和系统。

Use of global Registry causes your code to be tied to the class name of said Registry. 使用全局注册表会导致您的代码与所述注册表的类名绑定。 It means that you cannot test your code independently. 这意味着您无法独立测试代码。 And the way, how registry is set up, lies to you: you can never know which instance will be required. 而且,注册表的设置方式对你来说就是:你永远不知道需要哪个实例。

It is quite common for people to confuse DI Containers with Registries. 人们常常将DI容器与注册表混淆。

DI Container is not something that you inject into a class. DI容器不是你注入课堂的东西。 Instead it is an enhancement for factories: it determines that class Foo requires instance of Bar to be injected in the constructor. 相反,它是对工厂的增强:它确定类Foo需要在构造函数中注入Bar实例。 Then, depending on setup, it either acquires new instance of Bar or uses the existing one, to provide said dependency. 然后,根据设置,它要么获取Bar新实例,要么使用现有的实例来提供所述依赖关系。

  • In a simple factory you usually have to hard-code the dependencies, that will be injected. 在一个简单的工厂中,您通常必须硬编码将被注入的依赖项。 In this situation, what factory can build, is limited by "footprint" of class's constructor. 在这种情况下,工厂可以构建什么,受到类构造函数的“足迹”的限制。

  • When factory uses as DI container, it can produce instances with various dependencies. 当工厂用作DI容器时,它可以生成具有各种依赖关系的实例。 In this setup, your factories focus on constructing instances that are tied to some specific namespaces (or other high-level) logical groups of classes. 在此设置中,您的工厂专注于构建绑定到某些特定名称空间(或其他高级)逻辑类组的实例。

I think the point missing here is CompositionRoot .As per DI Principle once you define your bindings in the Composition Root , then you can use the reference throughout the application. 我认为这里缺少的是CompositionRoot 。根据DI原理,一旦在Composition Root中定义了绑定,就可以在整个应用程序中使用该引用。 That is the value DI Container brings. 这就是DI Container带来的价值。

As per definition "A Composition Root is a (preferably) unique location in an application where modules are composed together." 根据定义“组合根是应用程序中的一个(最好)唯一的位置,其中模块组合在一起。”

I will add that a Composition Root also a unique location where all important decisions about your applications behavior takes place. 我将添加一个组合根也是一个独特的位置,其中所有关于应用程序行为的重要决策都会发生。 That is what object to use in what situation.This is the heart of a OO system where interaction between the objects deliver the behavior of the system. 这就是在什么情况下使用的对象。这是OO系统的核心,其中对象之间的交互提供了系统的行为。

I agree with most of what teresko has said and i would like to add some points: 我同意teresko所说的大部分内容,我想补充一些观点:

  • If you feel that your services are shared among many different instances then you can register them as Singeltons with the container but then you will have to think about multi-threading if it is an issue for your. 如果您觉得您的服务是在许多不同的实例之间共享的,那么您可以将它们注册为Singeltons与容器,但是如果它是您的问题,您将不得不考虑多线程。
  • Whenever you feel that your back is against the wall in a dependency injection scenario then remember that factories (Abstract Factory Pattern) are almost always the solution. 每当你在依赖注入场景中感觉到背部靠墙时,请记住工厂(抽象工厂模式)几乎总是解决方案。
  • The services you mentioned seem like a cross-cutting concern so i would use AOP techniques to avoid bloating my codebase with those concerns, this will make the code much more cleaner. 你提到的服务似乎是一个跨领域的问题,所以我会使用AOP技术来避免我的代码库膨胀与这些问题,这将使代码更清洁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM