I like to invert dependencies whenever possible by depending mostly on abstraction and allowing the concrete implementations to be passed into the object by clients, or a factory. I've found this to be pretty conducive to testability and extensibility. Here's a simple example:
public class Feature {
private final IStrategy strategy; // interface
public Feature(IStrategy strategy) {
this.strategy = strategy;
}
}
However, I don't like to burden clients of this class with supplying the concrete implementation of IStrategy
, because usually the client doesn't care. I also don't want to provide a factory every time I do something like this, because I would end up with a LOT of factories. Here's what I usually like to do instead:
public class Feature {
private final IStrategy strategy; // interface
public Feature(IStrategy strategy) {
this.strategy = strategy;
}
public Feature() {
this(new DefaultConcreteStrategy());
}
}
Technically, Feature
has a direct dependency on DefaultConcreteStrategy
because it mentions it by name. The compile-time dependency will always be there. But the runtime dependency is effectively optional because motivated clients (unit tests, usually) can inject another concretion if desired.
Is this sound design? Is there a name for this pattern? Does anyone have a better or alternative approach?