I am often asked about Design Patterns. Do I know the book? Do I employ what have now become the classical, and eminently useful design patterns, or do I labor away producing less classical (and--gasp!--likely poorly conceived) classes, with an unseemly admixture of roles? Of course, I had to read the book to find out, and am happy to report that after a careful survey of the twenty three patterns therein, I have discovered the following:
All of the patterns from the book that I have used or improved upon are highlighted in yellow.
| Creational Patterns | |
|---|---|
| Abstract Factory (aka: Kit) | |
| Builder | First employed: 1986. |
| Factory Method | Employed this pattern regularly since 1989, with MacApp. |
| Prototype | yes |
| Singleton | yes |
| Structural Patterns | |
|---|---|
| Adapter (aka: Wrapper) | 1986 |
| Bridge (aka: Handle/Body) (aka: API/Implementation classes) | 1996-1998, 2001. This pattern is essential for the following reason: implementation is never truly separate from interface for any single class, given that its data representation is made known (even if it is private) to whoever #includes the class header. The only way to hide the implementation completely is through use of this pattern. Subclassing does not solve this problem, since APIs need their own hierarchies without being encumbered by implementation considerations, and implementations similarly need their own hierarchies to reuse code. I have made extensive use of this pattern as part of creating platform independent interface frameworks. I referred to these as API/Implementation classes. The API classes, are a hierarchy of classes which provide the application interface. They are 100% portable, and promote portable application development. Each API object makes only one concession to specific implementations: it recognizes they exist. Towards this end, API classes have a pointer to the implementation class. The actual type of the class in known only to the implementation of the API class, but is not published in its header. |
| Composite | 1986-1998: Use of this pattern is similarly unavoidable in the computer graphics field where groups of objects must act in every way if they where individual objects. |
| Decorator | Standard to most user interface frameworks |
| Facade | 1988: Critical to making complex sets of APIs which interact in subtle ways usable through a unified API which manages these subtleties. |
| Flyweight | 1989: Have made extensive use of this pattern as in the classic case presented, of character font information, and other user created shapes which have multiple instances, but each shares the same underlying data representation with separate flyweight objects that provide only unique position, transform, and color type information. |
| Proxy (aka: Surrogate) | 1993-1998: I have employed this pattern with both remote objects (using local stubs that encapsulate communication with the remote object), and with graphical objects that manage variable resolution data. |
| Behavioral Patterns | |
|---|---|
| Chain of Responsibility (aka: Functional or Visible Hierarchy) | As opposed to Class Hierarchies which define inheritance, Functional hierarchies show how commands are filtered and trapped through a set of candidate objects who are likely targets for the command. 1985-1988 As part of Artronics MenuMaker and all subsequent framework, and graphics software design; 1989: MacApp, 1991-1995 Think Class Library, 1995-1998 Live Picture Framework |
| Command (aka: Action, Transaction) | An integral part of most User Interface Frameworks since MacApp, and an exceptional technique for encapsulate do, undo, redo type functionality. 1989: MacApp, 1991: Think Class Library, 1995: Live Picture Framework |
| Interpreter | I have used this pattern in its most general form in conjunction with the composite pattern. |
| Iterator (aka: Cursor) | Used extensively since 1989. No good collection classes are possible without using iterators in conjunction with them to maintan separate state. It is the prefered technique for traversing lists and trees in a double loop, or from separate threads simultaneously. |
| Mediator | Essential similar to a Facade, the only difference being in the direction of communication between objects. (A mediator may be known to its constituent objects or not, and a Facade is more unidirectional) 1988- beginning with Cricket work on interfaces. |
| Memento (aka: Token) | My similar patterns do not meet all the criteria Design Patterns states for a Memento. I have made substantive use of encapsulated states that never warranted being treated as first class objects. The most similar thing to Memento that I have done is nearly the reverse (see ChunkServer below, in my improved version of the Visitor pattern). |
| Observer (aka: Dependents, Publish-Subscribe, Broadcast-Listen) | I have made massive use of this pattern, and have championed it throughout my career. It is the essence of the Model/View/Controller paradigm, and the cure to tight-coupling of model objects to their views/controllers where no such knowledge is desired or warranted. My key successes as a programmer have been largely due to the strict adoption of clean functional models. Programmers tend to subvert this paradigm to gain interactivity but do so at enormous cost to the longevity of their software. |
| State | 2003: This is a brilliant pattern, and I have needed it and sometimes come "close". And now I should kick myself that I didn't employ it, prior to learning of it from the GOF. It was a perfect fit for modifying connection class behavior for separate just connected/logged in/error states. |
| Strategy (aka Policy) | 1985-present. Numerous uses, some of them to modest to contemplate (e.g. families of validators). This pattern is just to close to OOP 101. Edge Highlighter 1995-1996: employed a variety of subsitutable algorithms that provided the same interface. |
| Template Method | This is among the most routine and obvious of patterns. I have used it innumerable times, for example in the design of collection class libraries. |
| Visitor | This is one of the least mature and most problematic of the patterns presented in Design Patterns. I have addressed the same issues more effectively. My very first critique of OOP was its tendency to produce "bloated" objects which were concerned with too many tasks, (e.g. Graphics objects that were concerned with their storage representation). My solution to this issue has been to create separate sets of related objects in a parallel hierarchy and to grant them access to the original classes data. For example, at MacroMind (1989-1991) I created the 'Chunkserver' set of classes(C++), which were strictly concerned with the serialization of objects. Each Serializable object made a single concession, that it had a "friend" class dedicated to the task. That left the functional classes unpolluted by specific serialization strategies, and rather than requiring the addition of serialization code to the object, only required adding a "friend" for that purpose. (And for those who believe that friends are "bad", this shows that everything has its legitimate purpose.) |