我应该通过构造函数注入在我的类中明确具体的类依赖吗?

时间:2010-10-26 06:49:52

标签: c# java oop dependency-injection

我正在设计一个小项目,我没有对所有类的接口使用编程。我发现有些类几乎不需要更改,所以我让它们被客户端类引用为具体类。

所以,假设我们ClassB消费了ClassA消费者:

alt text

class ClassB {
}

我的问题是,我应该在ClassB中创建ClassA,还是应该在层次结构中“提升”该责任?我将描述两种情况:

class ClassA {
    private ClassB classB;

    public ClassA() {
        this.classB = new ClassB();
    }
}

class ClassA {
    private ClassB classB;

    public ClassA(ClassB classB) {
        this.classB = classB;
    }
}

我想知道你将如何做到这一点以及背后的理由是什么!

由于

5 个答案:

答案 0 :(得分:3)

这取决于实施,没有一般答案。如果A具有初始化B的所有相关数据和知识,那么它可以初始化它。

如果您不希望A知道如何初始化B,或者您不想为初始化提供所有数据,那么您应该在外部创建它。

答案 1 :(得分:3)

第一个选项(A创建B)的一些优点:

  1. A级用户不需要知道B或如何创建&配置它。这使得编程模型更简单。
  2. B也可以是私有/内部的,因此你的图书馆用户不需要涉及他们不需要看的许多帮助类。
  3. 你可以改变A的工作方式,完全不使用B而不破坏调用代码。
  4. 封装 - 当A正在运行时,没有人从外部篡改B
  5. 第二个选项的一些优点(A依赖于B):

    1. A类用户可以完全控制B对象 - 他们可以采用不同的方式对其进行配置,如果需要,可以将同一个对象传递给A的多个实例。
    2. 它为传入的不同实现打开了大门(如果B是接口或基类),这对单元测试或可扩展性具有重要价值。
    3. 更新:如果将来创建B变得更加复杂(例如B有自己的某些依赖关系),那么可以在外部进行管理,而无需对A进行更改。 / LI>

      请注意,通过使用有时被称为“穷人的依赖注入”的方式,也可以创建“两全其美”的解决方案:

      class ClassA {
          private ClassB classB;
      
          public ClassA(ClassB classB) {
              this.classB = classB;
          }
      
          public ClassA() : this(new ClassB()) {
      
          }
      }
      

答案 2 :(得分:2)

你最好注入由ClassB实现的接口。

class ClassA {
private InterfaceB B;

public ClassA(InterfaceB B) {
    this.B = B;
}
}
class classB: InterfaceB
{
}

请注意,InterfaceB可能是常规类,作为派生类的基类。在这种情况下,它仍然作为接口。

答案 3 :(得分:1)

前者A承担了B类实例化的全部责任。所以,没有什么可以出错。 A知道B就像任何事情一样。如果A想要在调用任何方法之前设置很少的B属性。它可以通过在初始化之后设置它们来做到这一点。

在后者中,A无法确定B

现在,选择当然是你的。

答案 4 :(得分:0)

第二个选项的几个优点(通过构造函数传递对象,即反转控件)到目前为止还没有提到过:

1)您可以使用依赖注入工具来注入classB对象。虽然它不能注入不同的实现,因为你被锁定到具体类,它可以指定对象生命周期(单例,每请求,每线程)和用于实例化对象的任何构造函数参数。

2)如果你总是在构造函数中传递依赖关系(控制的反转),那么每个类的依赖关系一目了然可以说清楚了。