posted 12 years ago
As a rough guideline, a good starting point is, "Is this a very specialized type that only has this one particular useful form? Or is this a higher-level generality that might take different forms in how it's actually implemented, depending on which specific kind of use-case it's supposed to handle.
For instance, I recently wanted to be able to represent ranges, such as 1-5, 10-20 without having to specifically list every element, but still be able to iterate over all the elements, determine how many elements it had, determine whether a particular value was included in that range, etc. I could have just defined a Range<T extends Number> class and done simple arithmetic to realize that functionality. However, at about the same time, I also had a use for specifying ranges of IP addresses the same way, such as 192.168.0.* or 192.168.0.100-200. The operations I would want to do in both cases were the same, but the simple math that work for a range of numbers wouldn't work for IP addresses.
So I defined an interface Range<E extends Comparable<E>> extends Iterable<E>. There are one or two sub-interfaces, a couple of abstract classes, and a couple of concrete classes. I can now do stuff like: