Summary: Provide three “classes”: an interface, an abstract class, and a default implementation. [Design Pattern]
Context
You are developing a framework of cooperating classes.
Forces
- You want to make things easy for the user, so you want to provide implementations.
- But you want your design clean, and you want the user to provide implementations where appropriate.
Resolution
Provide three “classes”:
- An interface (fully abstract class), to keep the design clean.
- An abstract class (that conforms to the interface), that implements the “bookkeepping part of the class, but has abstract methods for the “interesting” parts.
- A fully-implemented class (probably a subclass of the abstract class, definitely conforming to the interface). This should provide a useful default implementation.
Discussion
This gives the user several places to “plug in.” The first cut (or a naive programmer) can work with the default implementation. A more sophisticated implementation can extend the abstract class, and avoid copying data into and out of the default implementation. An implementation for which the abstract version’s bookkeepping is too much overhead can replace everything. Finally, the interface provides a barrier to ensure clients don’t care (depend on) which actual types they’re working with.
Examples
- The Swing libraries for Java use this pattern. For instance, TableModel provides the interface. AbstractTableModel handles the change notification, and lets you wrap your own table structure with it. DefaultTableModel provides a table that uses Vector for storage.
[Written 6-1-98]