Reputation: 6649
What's the best practice when dealing with a situation like the following (simplified symbolic analogous case, not asking for a particular implementation solution):
Imagine I want to create a custom class that represents my physical Calendar at my office desktop. It can be translated in Java as a GregorianCalendar(myCustomZone).
So, I create a class such as:
class MyOfficeCalendar extends GregorianCalendar{
public MyOfficeCalendar(){
super(new SimpleTimeZone(...));
}
}
In these cases, code reviewers would say that instantiation in the constructor is a bad idea. But if I inject the SimpleTimeZone dependency into the constructor this seems to me like error prone, since my dependency only should be instantiated in a desired way. I want the control at that scope, not exposing the possibility of erroneous injection. I mean, that certain instantiation is part of my caller class behaviour or paradigm. The definition of MyOfficeCalendar is precisely a GregorianCalendar working with this particular custom TimeZone instance.
So what is the best design usually in those cases?
Force MyCalendar to be flexible enough for other non-intended uses which can make it incoherent and rely on a correct IoC container xml or a shared dev-user misconception since I am not forcing anything
Instantiate in the constructor the absolute desired dependence
Manage the Whole thing without my convenient OOP class (I like to adhere to the SingleResponsabilityPrinciple as much as I can)
Change the whole architecture ?
Upvotes: 1
Views: 114
Reputation: 51483
Introduce a builder to encapsulate the construction behavior. E.g.
public class MyOfficeCalendar extends GregorianCalendar{
public static class Builder {
private Integer rawOffset;
public void setRawOffset(int rawOffset) {
this.rawOffset = rawOffset;
}
public MyOfficeCalendar build(){
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
int effectiveRawOffset = tz.getRawOffset();
if(rawOffset != null){
effectiveRawOffset = rawOffset;
}
SimpleTimeZone simpleTimeZone = new SimpleTimeZone(effectiveRawOffset, tz.getID());
return new MyOfficeCalendar(simpleTimeZone);
}
}
private MyOfficeCalendar(SimpleTimeZone simpleTimeZone){
super(simpleTimeZone);
}
}
Client code can only set a few SimpleTimeZone
properties. How much it can set depends on your builder implementation.
The builder can be used as a factory bean in IoC Frameworks.
Upvotes: 1