The best designers in any field have an uncanny ability to see patterns that characterize a problem and corresponding patterns that can be ...
The best designers in any field have an uncanny ability to see patterns that characterize a problem and corresponding patterns that can be combined to create a solution. Gamma and his colleagues discuss this when they state:
[Y]ou’ll find recurring patterns of classes and communicating objects in many objectoriented systems. These patterns solve specific design problems and make object-oriented design more flexible, elegant, and ultimately reusable. They help designers reuse successful designs by basing new designs on prior experience. A designer who is familiar with such patterns can apply them immediately to design problems without having to rediscover them.
Throughout the OOD process, a software engineer should look for every opportunity to reuse existing design patterns (when they meet the needs of the design) rather than creating new ones.
Describing a Design Pattern
Mature engineering disciplines make use of thousands of design patterns. For example, a mechanical engineer uses a two-step, keyed shaft as a design pattern. Inherent in the pattern are attributes (the diameters of the shaft, the dimensions of the keyway, etc.) and operations (e.g., shaft rotation, shaft connection). An electrical engineer uses an integrated circuit (an extremely complex design pattern) to solve a specific element of a new problem. All design patterns can be described by specifying the following information :
• the name of the pattern
• the intent of the pattern
• the “design forces” that motivate the pattern
• the solution that mitigates these forces
• the classes that are required to implement the solution
• the responsibilities and collaboration among solution classes
• guidance that leads to effective implementation
• example source code or source code templates
• cross-references to related design patterns
The design pattern name is itself an abstraction that conveys significant meaning once the applicability and intent are understood. Design forces describe the data, functional, or behavioral requirements associated with part of the software for which the pattern is to be applied. In addition forces define the constraints that may restrict the manner in which the design is to be derived. In essence, design forces describe the environment and conditions that must exist to make the design pattern applicable.
The pattern characteristics (classes, responsibilities, and collaborations) indicate the attributes of the design that may be adjusted to enable the pattern to accommodate a variety of problems. These attributes represent characteristics of the design that can be searched (e.g., via a database) so that an appropriate pattern can be found. Finally, guidance associated with the use of a design pattern provides an indication of the ramifications of design decisions.
The names of objects and subsystems (potential design patterns) should be chosen with care. One of the key technical problems in software reuse is simply the inability to find existing reusable patterns when hundred or thousands of candidate patterns exist. The search for the “right” pattern is aided immeasurably by a meaningful pattern name along with a set of characteristics that help in classifying the object .
Using Patterns in Design
In an object-oriented system, design patterns can be used by applying two different mechanisms: inheritance and composition. Inheritance is a fundamental OO concept . Using inheritance, an existing design pattern becomes a template for a new subclass. The attributes and operations that exist in the pattern become part of the subclass.
Composition is a concept that leads to aggregate objects. That is, a problem may require objects that have complex functionality (in the extreme, a subsystem accomplishes this). The complex object can be assembled by selecting a set of design patterns and composing the appropriate object (or subsystem). Each design pattern is treated as a black box, and communication among the patterns occurs only via welldefined interfaces.
Gamma and his colleagues suggest that object composition should be favored over inheritance when both options exist. Rather than creating large and sometimes unmanageable class hierarchies (the consequence of the overuse of inheritance), composition favors small class hierarchies and objects that remain focused on one objective. Composition uses existing design patterns (reusable components) in an unaltered form.