我正在设计一个小项目,我没有对所有类的接口使用编程。我发现有些类几乎不需要更改,所以我让它们被客户端类引用为具体类。
所以,假设我们ClassB
消费了ClassA
消费者:
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;
}
}
我想知道你将如何做到这一点以及背后的理由是什么!
由于
答案 0 :(得分:3)
这取决于实施,没有一般答案。如果A具有初始化B的所有相关数据和知识,那么它可以初始化它。
如果您不希望A知道如何初始化B,或者您不想为初始化提供所有数据,那么您应该在外部创建它。
答案 1 :(得分:3)
第一个选项(A创建B)的一些优点:
第二个选项的一些优点(A依赖于B):
请注意,通过使用有时被称为“穷人的依赖注入”的方式,也可以创建“两全其美”的解决方案:
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)如果你总是在构造函数中传递依赖关系(控制的反转),那么每个类的依赖关系一目了然可以说清楚了。