I follow more or less the pattern I initially learned from Swing. I have an interface then I create either a "Base" or an "Adapter" class. For me, an adapter will often have do-nothing implementations for all of the interface methods, to allow an implementor to write just the methods they need while ignoring the others. A base will be an abstract class that provides convenient implementations for some of the interface methods - hopefully the "most likely" implementation.
For example, I have a SearchFilter interface that, among other things, has an apply(Collection<T>)
method. That method will almost always loop through the collection and call the interface method boolean include(T item)
to decide whether or not to keep or filter out the item. My SearchFilterBase provides that as an implementation for apply() and an implementor only has to write their include() logic.
Implementors are free, of course, to simply implement the whole interface themselves and not derive from the Base, which is the advantage over changing the interface to an abstract class, which forces them to use their single inheritance (This is the problem with java.util.Observable)
In response to N8g's comment - You can subclass the base or adapter but are not required to subclass -- you can implement the interface yourself from scratch. The base or adapter is provided as a convenience, implementing no-op methods so you don't have to do it, or implementing convenient common functionality in an abstract base class (like my SearchFilterBase
class). The advantage this has over turning the interface into an abstract class is that you don't force inheritance from your abstract class.