[Dependency-injection] 为什么要使用依赖注入?


Answers

我认为很多时候人们对依赖注入和依赖注入框架 (或者它经常被称为的容器 )之间的区别感到困惑。

依赖注入是一个非常简单的概念。 代替这个代码:

public class A {
  private B b;

  public A() {
    this.b = new B(); // A *depends on* B
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  A a = new A();
  a.DoSomeStuff();
}

你写这样的代码:

public class A {
  private B b;

  public A(B b) { // A now takes its dependencies as arguments
    this.b = b; // look ma, no "new"!
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  B b = new B(); // B is constructed here instead
  A a = new A(b);
  a.DoSomeStuff();
}

就是这样。 认真。 这给你很多好处。 其中两个重要的功能是从中心位置( Main()函数)控制功能,而不是将其分散到整个程序中,并且可以更轻松地单独测试每个类(因为您可以将模拟对象或其他伪造对象传入它的构造函数而不是真正的价值)。

当然,缺点是你现在有一个超级函数可以知道你的程序使用的所有类。 这是DI框架可以提供帮助的。 但是,如果您无法理解为什么这种方法很有价值,那么我建议首先从手动依赖注入入手,这样您可以更好地理解那里的各种框架可以为您做些什么。

Question

我试图理解依赖注入 (DI),并再次失败。 它看起来很愚蠢。 我的代码从来都不是一团糟; 我几乎不写虚拟函数和接口(虽然我只做了一次蓝月亮),并且所有配置都使用json.net(有时使用XML序列化程序)奇迹般地序列化为一个类。

我不太明白它解决了什么问题。 它看起来像是一种说法:“嗨,当你遇到这个函数时,返回一个这种类型的对象并使用这些参数/数据。”
但是......为什么我会使用它? 注意我从来不需要使用object ,但我明白这是什么意思。

在建立一个使用DI的网站或桌面应用程序时,有哪些真实情况? 我可以很容易地想出为什么有人可能想要在游戏中使用接口/虚函数的情况,但是它非常罕见(很少有我不记得单个实例)在非游戏代码中使用它。




我认为经典答案是创建一个更加分离的应用程序,它不知道在运行时将使用哪个实现。

例如,我们是中央支付提供商,与世界各地的许多支付提供商合作。 但是,当提出请求时,我不知道要拨打哪个付款处理器。 我可以用一大堆开关盒编写一节课,例如:

class PaymentProcessor{

    private String type;

    public PaymentProcessor(String type){
        this.type = type;
    }

    public void authorize(){
        if (type.equals(Consts.PAYPAL)){
            // Do this;
        }
        else if(type.equals(Consts.OTHER_PROCESSOR)){
            // Do that;
        }
    }
}

现在想象一下,现在你需要将所有这些代码保存在一个类中,因为它没有正确解耦,你可以想象,对于你将支持的每个新处理器,你需要创建一个新的if // switch case for然而,通过使用依赖注入(或控制反转 - 有时称为,意味着控制程序运行的任何人只在运行时才知道,而不是并发症),那么这只会变得更加复杂,您可以实现某些非常整洁和可维护。

class PaypalProcessor implements PaymentProcessor{

    public void authorize(){
        // Do PayPal authorization
    }
}

class OtherProcessor implements PaymentProcessor{

    public void authorize(){
        // Do other processor authorization
    }
}

class PaymentFactory{

    public static PaymentProcessor create(String type){

        switch(type){
            case Consts.PAYPAL;
                return new PaypalProcessor();

            case Consts.OTHER_PROCESSOR;
                return new OtherProcessor();
        }
    }
}

interface PaymentProcessor{
    void authorize();
}

**代码不会编译,我知道:)