简体   繁体   English

OOP依赖关系:依赖注入与注册表

[英]OOP Dependencies: Dependency Injection vs. Registry

I know some OOP and have read this and that, but am not a hardcore OOP guy and have no formal training and can't rattle off why something should use dependency injection or not, and may not be able to identify all dependencies in a design, hence my question. 我知道一些OOP并且已经读过这个和那个,但是我不是一个硬核OOP人并且没有正式的训练并且无法解释为什么某些东西应该使用依赖注入,并且可能无法识别设计中的所有依赖项因此我的问题。

Answering a question here on SO ( Using a object in methods of other objects ) I started to doubt myself. 在这里回答一个问题( 在其他对象的方法中使用对象 )我开始怀疑自己。 As far as dependencies, is one of these better or worse or both acceptable? 就依赖性而言,其中一种更好还是更差,还是两者都可以接受? Any design limitations? 任何设计限制?

I have read and understand both but haven't ever come across a comparison. 我已阅读并理解两者,但从未遇到过比较。 Why would one be better used in a design, etc. 为什么在设计中更好地使用它等等。

Dependency Injection: 依赖注入:

class myClass {
    private $db;

    public function __construct($db) {
        $this->db = $db;
    }
}

Registry (maybe also something else): 注册表(也许还有别的):

class myClass {
    private $db;

    public function __construct() {
        $this->db = Registry::get('db');
    }
}

It has a lot to do with testability. 它与可测试性有很大关系。

In your example, the first (Dependency Injection) is better. 在您的示例中,第一个(依赖注入)更好。 The reason it's better is because it accepts db as an argument, which means this is testable, you can use a mock db for testing and test myClass does the right thing with it. 它更好的原因是因为它接受db作为参数,这意味着这是可测试的,你可以使用模拟db进行测试和测试myClass做正确的事情。

The second example (Registry) is not recommended as not only myClass depends on db , it now also depends on Registry , and the worst part it's that it knows how to get a db . 不建议使用第二个示例(注册表),因为不仅myClass依赖于db ,它现在还依赖于Registry ,最糟糕的是它知道如何获取db It's too smart, it should be dumb like the first one, dumb things are more testable, smart things are not. 它太聪明了,它应该像第一个一样愚蠢,愚蠢的东西更容易测试,聪明的东西不是。

Both methods are possible implementations of dependency injection. 两种方法都是依赖注入的可能实现。 Basically dependency injection means to define a way to configure (inject) the classes to be used at runtime in order to make to code more flexible compared to using using hard coded class names and constructors in the code. 基本上,依赖注入意味着定义一种配置(注入)要在运行时使用的类的方法,以便与在代码中使用硬编码类名和构造函数相比,使代码更灵活。 Dependency injection follows a principle called inversion of control . 依赖注入遵循称为inversion of control原则。

This is especially interesting for testing code but can be used in a variety of other scenarios where you want to make an application flexible and maintainable. 这对于测试代码尤其有用,但可以用于您希望使应用程序灵活和可维护的各种其他场景中。

While dependency injection mostly is referred to as DI container , it can generally be done using a couple of different methods - which may also coexist. 虽然依赖注入主要被称为DI container ,但通常可以使用几种不同的方法来完成 - 这些方法也可以共存。 Here comes an (incomplete) list: 这是一个(不完整的)列表:

  • using a dependency injection container 使用依赖注入容器
  • pass class dependency as constructor or method args 将类依赖项作为构造函数或方法args传递
  • using a central registry (as long as it is configurable) 使用中央注册表(只要它是可配置的)
  • using setter methods to set dependencies 使用setter方法设置依赖项
  • using configuration files 使用配置文件
  • user input 用户输入
  • ... ...

A dependency injection is required because the object needs certain data to perform its functions correctly. 需要依赖注入,因为对象需要某些数据才能正确执行其功能。

Dependency Injection can be performed in three different ways: 依赖注入可以通过三种不同的方式执行:

  • If Object A depends on object B, then you can create object A while creating object B 如果对象A依赖于对象B,则可以在创建对象B时创建对象A.
  • You can use some external class ( like Registry, configuration files etc ) to load the dependency objects, This will decouple the creation of your object from the dependency creation. 您可以使用一些外部类(如注册表,配置文件等)来加载依赖项对象,这将使对象的创建与依赖项创建分离。 This is called locator pattern where your object creation is dependent upon the locator to load the objects. 这称为定位器模式,其中您的对象创建依赖于加载对象的定位器。
  • You can create the dependency elsewhere and provide it directly to the dependent object. 您可以在其他位置创建依赖项,并将其直接提供给依赖对象。 This is called 'manual injection' 这称为“手动注射”

Whenever you do any of these, you are already doing dependency injection: 无论何时执行这些操作,您都在进行依赖注入:

Constructor injection 构造函数注入

public class ClassA
{
 // declares the dependency in the constructor

 public function ClassA( dependency1:String )
 {}
}

// and the dependency is created while instantiating the object
var objA:ClassA = new ClassA("Hello World");

Public property injection 公共财产注入

public class ClassA
{
 // declares the dependency as a public property
 public var helloStr:String;
}

var obj1:ClassA = new ClassA();

// dependency is fulfilled by setting a public property after instantiation:
obj1.helloStr = "The Zen Master";

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

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