java configuration/parameter passing design
Often I find the need to engineer objects with configurable functionality.
To exemplify, assume I'm creating a DateIterator
. The configurable option(s) might be whether to iterate the closed interval [start, end]
or the open-end interval [start, end)
.
- (1) The, in my opinion, ungraceful solution - lim开发者_Python百科ited to only one true/false configuration option
new DateIterator(boolean openInterval);
- (2) The typesafe enum way - typically a bit bulky
new DateIterator(Interval.OPEN_END);
- (3) The unconventional attempt - nice but not too straight forward
new DateIterator().openEnd();
- (4) The inheritance approach - often over-engineering
new OpenEndedDateIterator();
To this comes a few alternatives which I consider inferior, like integer-based configuration new DateIterator(Interval.OPEN_END);
or property based configuration.
Are there any other approaches? Which approach you do you prefer?
I'd say the Builder pattern makes sense here:
DateIterator di =
DateIterator.builder()
.withStartDate(new Date())
.withOpenEnd()
.build();
That way your actual DateIterator can be immutable, while the builder returned by DateIterator.builder()
does the configuration work.
While there is no good answer, and it's largely a matter of taste, I do follow the following rule of thumb, with large space for exceptions to avoid over engineering :
- If the only configuration you have is one "parameter", taking a fixed set, and alters behavior (like in your example), go with subclasses. While it may be over-engineered, if many methods in your class start with an "if (this.parameter == x) ... else if (this.parameter == y) .. " it will make code unreadable.
- If your parameter is not a fixed set, but a string or number, and you NEED it for the class to work properly put it in the constructor, if it's not mandatory i like solution number (3), the unconventional attempt :)
- If you have more than one parameter in a fixed set (like START_OPEN_ENDED and STOP_OPEN_ENDED), creating subclasses may mean to create a subclass for each permutation. In that case consider encapsulation. For example (I would not do it in this specific case probably, but it's a good example), create a single class DateComparator, with a subclass for open ended, and encapsulate a DateComparator for the start and one for the end, having only one DateIterator.
Again, these are the rule of thumb I use, in no way mandatory, and often I find myself not respecting them verbatim.
精彩评论