Robert Abbott and "Strider" Classifying Patterns Part 1 - Attemping A Complete Classification 1.1 "Santa Fe, Albuquerque, and Farmington" 1.1.1 Description "SantaFe, Albuquerque, and Farmington" places each pattern into one of three groups based on how popular and widely applicable the pattern is. "Santa Fe" patterns are those that all pattern users have at least heard about, and likely have used. Criticism of a Santa Fe pattern is taboo, because Santa Fe patterns are widely regarded as Gospel. "Albuquerque" patterns are known to a smaller, but still sizeable portion of pattern users. Albuquerque patterns are of somewhat limited applicability, so an Albuquerque Pattern is more likely known to a designer working in a field related to the pattern. "Farmington" patterns have very limited applicability. They are probably familiar only to those who have sought them out to meet some specific need (or who read patterns books from cover to cover). 1.1.2 Applicability Grouping patterns by their popularity serves several purposes. Those new to patterns should focus on Santa Fe patterns because they best convey the pattern concept, arise more frequently in software design, and have the most standardized names and definitions. Teachers of patterns should present most useful ones first. The patterns community should publish pattern collections without mixing Sante Fe and Farmington patterns because the two are of interest to different groups. Santa Fe patterns should all be presented together, because they're all generally useful. Farmington patterns, which are more numerous, should be published in focused collections to appeal to specialists. 1.1.3 Definition Santa Fe Patterns: Abstract Factory, Singleton, Adapter, Proxy, Observer Albuquerque Patterns: Prototype, Bridge, Composite, Decorator, Facade, Command, Iterator, Mediator, Template Method Farmington Patterns: Builder, Factory Method, Flyweight, Chain of Responsibility, Interpreter, Memento, State, Strategy, Visitor Part 2 - Groupings 2.1 "Glue" 2.1.1 Description "Glue" patterns are applied to integrate or reuse software that wouldn't otherwise work together. A system built from the ground up by a single coherent team would use little or no glue. In practice, there is usually some software to reuse and incomplete specifications result in the need for integration. Most glue patterns also serve other purposes, typically decoupling. The glue pattern is characterized by a single class in the pattern which conforms to the others, allowing the other to work together without modification. 2.1.2 Applicability Designers should use glue sparingly because it is essentially overhead incurred by necessity. Software maintainers must take care not to build up inflexible, chaotic software components using repeated applications of glue. Big globs of glue should sometimes be removed and replaced with a single well-engineered component (in essence serving the purpose that has been discovered over time and is manifest in the buildup of glue). On the other hand, some designers and programmers spend too much time reworking and refactoring software just to avoid applying a little glue. 2.1.3 Definition Glue Patterns: Adapter - The primary purpose of this pattern is to 'adapt' one interface to another, required interface Decorator - These may be designed in, but also can be used to add functionality to existing classes because the decorator has the same interface as the class Facade - Besides simplifying the interface to a group of classes, the facade is a more general Adaptor, since it hides not only function prototypes but also the number of classes used to implement the interface Proxy - Because a Proxy doesn't change the interface of what it represents (GOF 216), it can be 'dropped in' 'after the fact' to increase security or performance without recoding users of the interface. 2.2 "Misers" 2.2.1 Description Design patterns typically optimize for design purity at the cost of runtime efficiency. Patterns tend to introduce costly levels of indirection and increase the multiplicity of classes and, at runtime, class instances. The efficiency of Fortran-style programming (using big homogeneous arrays of unstructured data) is eschewed. It could be argued that design patterns tend to benefit the creators of software at the cost of its users. However, some patterns buck this trend. These patterns save memory or execution time through techniques such as lazy instantiation and initialization. 2.2.2 Applicability "Miser" patterns reduce the temptation to disregard design purity when efficient execution is a requirement, because Misers balance both of these needs. Knowing which patterns to consider when performance is unacceptable can help architects, designers, and implementers come to agreement on a course of corrective action. 2.2.3 Definition Miser Patterns: Singleton - Delaying instantiation improves startup time. If the object is never used, both execution time and memory usage are spared by never creating the object. Flyweight - The stated purpose of this pattern is to "support large numbers of fine-grained objects efficiently" (GOF 195). Proxy - Proxies can support delayed creation (as in the ImageProxy example, GOF 207) or provide caching. Strategy - Allows the fastest or most memory-efficient algorithm for a data set to be selected dynamically. 2.3 "Transformers" 2.3.1 Description Computing languages vary in whether features are implemented at compile-time or run-time. Interpreted languages have no compilation step and tend to offer more runtime flexibility, such as the run-time construction of classes or the execution of dynamically generated code. Compiled languages often do more compile-time verification of programs, at the cost of runtime flexibility. Transformer patterns show how to meet the need for runtime flexibility using compiled languages. 2.3.2 Applicability Transformers should be applied when a specific need for dynamic behavior has been determined. Using Transformers indiscriminately leads to a combinatorial explosion in the number of possible behaviors. Though potentially harmful for reliability, Transformers can add new levels of flexibility to programs. 2.3.3 Definition Transformers: Abstract Factory - Prevents hard-coding of the type of object to create. For instance, an abstract factory can decide what type of widget to create based on the currently selected look-and-feel. Builder - In this pattern, the Director can construct different classes of objects based on its current settings. Factory Method - In this case, neither the caller nor the Creator object decides what class to finally instantiate - a subclass of the Creator does. Decorator - Decorators can be attached to objects at runtime to alter a program's behavior and appearance. Chain of Responsibility - This very dynamic pattern allows a request to be offered to each handler in a sequence until one of the handlers takes action. Strategy - The various algorithms implementing an interface can vary in behavior, and one strategy can replace another at runtime (GOF 315) 2.4 "Access patterns" 2.4.1 Description Each of these patterns provides a way for objects to find and use each other without the aditional coupling or poor performance of simple-minded approaches 2.4.2 Applicability Maintaing low coupling can make it difficult to "get there from here." When one object needs to communicate with another without aggregating it, these patterns should be considered. 2.4.3 Definition Access Patterns: Proxy - Controls access to a service-providing object. [Grand80] Facade - Provides one object that all objects outside the set use to communicate with (access) the set. [Grand205] Adapter - Implements an interface known to its clients and provides access to an instance of a class not known to its clients. [Grand177] Cache Management - This pattern allows more then provides access. Allows fast access to objects that would otherwise take a long time to access (construction of these objects is expensive). [Grand251] 2.5 "Service Providers" 2.5.1 Description These patterns provide needed access or functionality 2.5.2 Applicability When a use case is found to require functionality not supported by an existing class design, one of the patterns may be useful. 2.5.3 Definition Service Providers: Iterator - Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation. [gof257] Layered Initialization - Objects that participate in this pattern cooperate to provide a service to objects outside the pattern. [Grand147] Snapshot - Provides a mechanism that saves and restores an object's state independently of the objects internal structure. [Grand334] Facade - Provides one object that all objects outside the set use to communicate with the set. [Grand205] Decorator - Provides the ability to dynamically alter the behavior of individual objects by adding and removing wrappers. [Grand247] 2.6 "DeCopuling" 2.6.1 Description Coupling is an important measure of complexity in a system. The larger the project, the more important that changes have only local impact. 2.6.2 Applicability Designers should employ these patterns to simplify systems and allow several developers to work in parallel. These patterns can also help 'rescue' a project whose design has degraded into unintelligible interdependent blobs. 2.6.3 Definition Decoupling Patterns: Facade - The facade pattern reduces or eliminates the coupling between a client class and the classes that implement an abstraction. [Grand208] Adapter - The client and adaptee classes are decoupled from each other. [Grand180] Proxy - Decouples a service-providing object from the classes using the service. [Grand80] Iterator - A class that accesses a collection only through such an interface (the interface defined by Iterator) is decoupled from the class that implements the interface. [Grand185] Bridge - Decouples an abstraction from its implementation so that the two can vary independently. [gof151] Snapshot - The mechanism for saving and restoring an object's state is decoupled from the objects internal structure. [Grand334] Builder - Decouples the construction of an object from its representation. [gof97] Mediator - Uses one object to coordinate state changes between other objects resulting in decreased coupling between the other objects. [Grand315] 2.7 "Guard Patterns" 2.7.1 Description Software Engineers are only human, and sometimes cause problems by forgetting the original intent of a class or the interrelationships beteween objects. Although no class design is 'idiot-proof,' Guard Patterns take a defensive stance to prevent mistakes. 2.7.2 Applicability When a bug is found, it's a good idea to ask what went wrong. Perhaps one of these patterns can be employed, creating a structural barrier to the reintroduction of the bug somewhere else. 2.7.3 Definition Guard Patterns: Proxy - Guard's (or controls) access to the real subject. [gof207] Singleton - The Singleton class ensures that no other instances can be created. It does this by intercepting requests to create new objects. [gof127] It guards the class constructor. 2.8 "Enablers" 2.8.1 Description The key work to this pattern is 'allows.' The aim of these patterns is to provide needed functionality. 2.8.2 Applicability Consider employing an "Enabler" when the existing class structure isn't flexible enough. 2.8.3 Definition Observer - Enables objects to dynamically register dependencies between objects. [Grand347] Prototype - Enables objects to be created using a prototype object. New objects are created by copying this prototype. [gof117] Strategy - Enables the selection of an algorithm to vary by object and over time. [Grand371] Adapter - Enables classes work together that couldn't otherwise because of incompatible interfaces. [gof139] Composite - Enables clients to treat individual objects and compositions of objects uniformly. [gof163] Filter - Enables objects that perform different transformations and computations on streams of data and that have compatible interfaces to dynamically connect. [Grand155] Proxy - Enables lazy creation of an object [Grand82]. Command - Using this pattern enables you to sequence, queue, undo, and otherwise manipulate commands. [Grand277] (Enables the control and manipulation of commands.) 2.9 "Encapsulation" 2.9.1 Description Encapsulation is related to decoupling, but consists of protecting an object's attributes rather than reducing its dependency on other classes' interfaces. Encapsulation is critical to managing system complexity. 2.9.2 Applicability Hardly anyone will argue that encapsulation is, in general, a Good Thing, but the real question is how to maintain encapsulation while offering all required functionality. These patterns show how to accomplish common tasks while provide only the needed amount of access to objects' methods and state. 2.9.3 Definition Patterns for Encapsulation Mediator - Defines an object that encapsulates how a set of objects interacts. [gof273] State - Encapsulates the states of an object as discrete objects. [Grand357] Strategy - Defines classes that encapsulate algorithms. [gof315] Command - Encapsulates commands in objects. [Grand277] Abstract Factory - Concrete classes are independent of the classes that use them and initiate their creation, because the abstract factory class encapsulates the process of creating them. [Grand103] Layered Initialization - This pattern works by encapsulating the common and specialized logic to create an object in unrelated classes. [Grand145]