Reputation: 4081
I'm working on a kind of parameter values parser library. I'd like to have an Parser defined as follows:
public class Parser {
private ValuesConfiguration configuration;
private ValuesProvider valuesProvider;
private ValuesMapper valuesMapper;
public Parser(ValuesConfiguration configuration) {
this.configuration = configuration;
}
public Result parse(String parameterName) {
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
}
I'd like this library clients to be unaware of ValuesProvider and ValuesMapper default implementations and use it like
Result result = new Parser(myConfig).parse("sampleParam");
Although there must be possibility to set their own implementations when needed. I wonder how and where should I init those default implementations and still let clients to set their own if they want. I don't want to stick to
new DefaultValuesProvider()
etc. in constructor, because default implementation would e.g. access filesystem, so that it would be hard to test (mock them out). I know I can use setters (like in DI) but what about defaults?
EDIT: After your all answer, I guess it is best here to have setters to allow clients to provider their own implementations of ValuesProvider and ValuesMapper. But how to create default implementations? I'd like to decouple instantiation from logic, so I don't want to use new DefaultValueProvider() here. Is the factory pattern applicable here? If so how and where should I use it?
Upvotes: 0
Views: 150
Reputation: 70564
How about:
public void setValuesProvider(ValuesProvider valuesProvider) {
this.valuesProvider = valuesProvider;
}
public Result parse(String parameterName) {
if (valuesProvider == null) {
valuesProvider = new DefaultValuesProvider();
}
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
As Mark points out, constructor injection might be the better way to go. That would look as follows:
public Parser(ValuesConfiguration configuration) {
this(configuation, new DefaultValuesProvider());
}
public Parser(ValuesConfiguration configuration, ValuesProvider valuesProvider) {
this.configuration = configuration;
this.valuesProvider = valuesProvider;
}
public Result parse(String parameterName) {
List<Values> values = valuesProvider.getValues(parameterName);
// do other stuff on values
// ...
return valuesMapper.transformValues(values, configuration);
}
I also agree with his summary of advantages:
This would enable you to make the dependency final/readonly. Property Injection provides quite weak guarantees about invariants - e.g. you could keep changing the dependency on the same instance, and that's probably not what you want.
However, there are also disadvantages:
My recommendation therefore is to use setter injection, and if it is necessary to prevent the reassignment of dependences, do:
public void setValuesProvider(ValuesProvider valuesProvider) {
if (this.valuesProvider != null) {
throw new IllegalStateException("Dependency already set");
}
this.valuesProvider = valuesProvider;
}
Upvotes: 2
Reputation: 20077
Use Google Guice or similiar Dependency Injection framework:
http://code.google.com/p/google-guice/
It's perfect for your needs. You can configure several modules describing what implementations will be instantiated for particular interfaces. You can have a ProductionModule and UnitTestModule for example.
Upvotes: 0