Design patterns provide the cores of ready-made solutions that can be used to
1067
solve many of software’s most common problems. Some software problems
1068
require solutions that are derived from first principles. But most problems are
1069
similar to past problems, and those can be solved using similar solutions, or
1070
patterns. Common patterns include Adapter, Bridge, Decorator, Facade, Factory
1071
Method, Observor, Singleton, Strategy, and Template Method.
1072
Patterns provide several benefits that fully-custom design doesn’t:
1073
Patterns reduce complexity by providing ready-made abstractions
1074
If you say, “Let’s use a Factory Method to create instances of derived classes,”
1075
other programmers on your project will understand that you are suggesting a
1076
fairly rich set of interrelationships and programming protocols, all of which are
1077
invoked when you refer to the design pattern of Factory Method.* You don’t
1078
have to spell out every line of code for other programmers to understand your
1079
proposal.
1080
Patterns reduce errors by institutionalizing details of common solutions
1081
Software design problems contain nuances that emerge fully only after the
1082
problem has been solved once or twice (or three times, or four times, or ...).
1083
Because patterns represent standardized ways of solving common problems, they
1084
embody the wisdom accumulated from years of attempting to solve those
1085
problems, and they also embody the corrections to the false attempts that people
1086
have made in solving those problems.
1087
Using a design pattern is thus conceptually similar to using library code instead
1088
of writing your own. Sure, everybody has written a custom Quicksort a few
1089
times, but what are the odds that your custom version will be fully correct on the
1090
* The Factory Method is a pattern that allows you to instantiate any class derived
from a specific base class without needing to keep track of the individual derived classes anywhere but the Factory Method. For a good discussion of the Factory Method pattern, see “Replace Constructor with Factory Method” in Refactoring
(Fowler 1999).
KEY POINT
first try? Similarly, numerous design problems are similar enough to past
1091
problems that you’re better off using a prebuilt design solution than creating a
1092
novel solution.
1093
Patterns provide heuristic value by suggesting design alternatives
1094
A designer who’s familiar with common patterns can easily run through a list of
1095
patterns and ask, “Which of these patterns fits my design problem?” Cycling
1096
through a set of familiar alternatives is immeasurably easier than creating a
1097
custom design solution out of whole cloth. And the code arising from a familiar
1098
pattern will also be easier for readers of the code to understand than fully custom
1099
code would be.
1100
Patterns streamline communication by moving the design dialog to a
1101
higher level
1102
In addition to their complexity-management benefit, design patterns can
1103
accelerate design discussions by allowing designers to think and discuss at a
1104
larger level of granularity. If you say, “I can’t decide whether I should use a
1105
Creator or a Factory Method in this situation,” you’ve communicated a great
1106
deal with just a few words—as long as you and your listener are both familiar
1107
with those patterns. Imagine how much longer it would take you to dive into the
1108
details of the code for a Creator pattern and the code for a Factory Method
1109
pattern, and then compare and contrast the two approaches.
1110
If you’re not already familiar with design patterns, Table 5-1 summarizes some
1111
of the most common patterns to stimulate your interest.
1112
Table 5-1. Popular Design Patterns
1113
Pattern Description
Abstract Factory
Supports creation of sets of related objects by specifying the kind of set but not the kinds of each specific object.
Adapter Converts the interface of a class to a different interface
Bridge Builds an interface and an implementation in such a way that either can vary without the other varying.
Composite Consists of an object that contains additional objects of its own type so that client code can interact with the top-level object and not concern itself with all the detailed objects.
Decorator Attaches responsibilities to an object dynamically, without creating specific subclasses for each possible configuration of responsibilities. Facade Provides a consistent interface to code that wouldn’t otherwise offer a
consistent interface. Factory
Method
Instantiates classes derived from a specific base class without needing to keep track of the individual derived classes anywhere but the Factory Method.
Iterator A server object that provides access to each element in a set sequentially.
Observor Keeps multiple objects in synch with each other by making a third object responsible for notifying the set of objects about changes to members of the set.
Singleton Provides global access to a class that has one and only one instance. Strategy Defines a set of algorithms or behaviors that are dynamically
interchangeable with each other. Template
Method
Defines the structure of an algorithm but leaves some of the detailed implementation to subclasses.
If you haven’t seen design patterns before, your reaction to the descriptions in
1114
Table 5-1 might be “Sure, I already know most of these ideas.” That reaction is a
1115
big part of why design patterns are valuable. Patterns are familiar to most
1116
experienced programmers, and assigning recognizable names to them supports
1117
efficient and effective communication about them.
1118
The only real potential trap with patterns is feature-itis: using a pattern because
1119
of a desire to try out a pattern rather than because the pattern is an appropriate
1120
design solution.
1121
Overall, design patterns are a powerful tool for managing complexity. You can
1122
read more detailed descriptions in any of the good books that are listed at the end
1123
of this chapter.
1124