Summary: This pair of patterns is inspired by some of the design decisions in the Java class library.
Marker Class
AKA Tagging Class
Example: You would like to have all objects provide a clone method. This is a generally useful facility, so you want it high in the hierarchy, but it’s potentially an expensive method, so you don’t want to require every object to be required to actually implement the clone method.
Problem: In an object-oriented framework, you must resolve general availability of a particular method against the expense of providing a capability everywhere.
Resolution: Make the method available high in the hierarchy (e.g., at the Object root class), but provide a special interface that defines the ability to really provide the method. The interface provides no data or methods, but any class implementing the interface guarantees that it will provide a useful implementation of the special method.
interface Capability {}
The special method is only valid for classes that “implement” that interface. (It’s a tagging interface because there may be no work – just an indication that the capability is desirable for this object.) Usually the special method will have the ability to throw an exception, in case it is called with a class that doesn’t implement the interface.
Usage: Java uses this for cloning and for serialization. For serialization, presence of the tagging interface tells the compiler it must generate extra code to handle reading and writing the object.
Fully Implemented Abstract Class
Example: The JDK 1.1 event model has Listener classes which must provide methods to handle several event types. For example, a ComponentListener must provide methods for componentAdded() and componentRemoved(). But, simple listeners do not need notification of all possible aspects of an event.
Problem: You have an interface with several methods, but not all subclasses need all methods.
Resolution: Provide an adapter class. The adapter is an abstract class, so it needs to be subclassed to be used, but it provides a dummy implementation of every method the interface requires. The subclass then needs to implement only the methods it requires.
Usage: Java uses this method for many event listeners in the JDK 1.1 event model – all the ones that require more than one method. (There’s no point in using the technique for listeners with one method, as that method would always be over-ridden.)