Reputation: 105067
I am doing the design of a small project where I didn't use programming against interfaces for all my classes. I found that some classes would hardly ever be needed to change, so I let them be referenced by their client classes as concrete classes.
So, let's say we have ClassB
that'll be consumed be consumed by ClassA
:
class ClassB {
}
My question is, should I create ClassB
in ClassA
, or should I pass that responsability "up" in the hierarchy? I'll depict both cases:
class ClassA {
private ClassB classB;
public ClassA() {
this.classB = new ClassB();
}
}
or
class ClassA {
private ClassB classB;
public ClassA(ClassB classB) {
this.classB = classB;
}
}
I'd like to hear about how would you do it and what'd be the rationale behind it!
Thanks
Upvotes: 10
Views: 1546
Reputation: 1008
A couple of advantages for the second option (passing the object via the constructor, i.e. inverting control) that haven't been mentioned so far:
1) You can use a dependency injection tool to inject the classB object. Although it can't inject different implementations because you are locked to the concrete class, it can specify the objects life-cycle (singleton, per-request, per-thread) and any constructor parameters used to instantiate the object.
2) If you always pass dependencies in the constructor (inversion of control) then it is arguably clearer which dependencies each class has at a glance.
Upvotes: 0
Reputation: 49482
Some advantages of your first option (A creates B):
Some advantages of your second option (A takes a dependency on B):
Note that it is also possible to create a "best of both worlds" solution by using what is sometimes called "poor man's dependency injection":
class ClassA {
private ClassB classB;
public ClassA(ClassB classB) {
this.classB = classB;
}
public ClassA() : this(new ClassB()) {
}
}
Upvotes: 3
Reputation: 7351
you'd better inject interface which implemented by ClassB.
class ClassA {
private InterfaceB B;
public ClassA(InterfaceB B) {
this.B = B;
}
}
class classB: InterfaceB
{
}
Please note that InterfaceB may be a regular class as base class for your derived ones. In this case it still works as interface.
Upvotes: 2
Reputation: 39907
In the former A
is taking the full responsibility of class B
instantiation. So, there is nothing which can go wrong. A
knows B
like anything. In case A
wants few of the B
properties to be set before invoking any method on it. It can do that by setting those just after intialisation.
In the latter, A
can't be that sure of B
.
Now, the choice is of course yours.
Upvotes: 1
Reputation: 5658
It depends on the implementation, there is no general answer. If A has all the relevant data and knowledge to initialize B, then it could initialize it.
If you don't want A to know how to initialize B or you don't want to give A all the data for the initialization, then you should create it externally.
Upvotes: 3