|
"Designing object-oriented software is hard, and designing
reusable object-oriented software is even harder.
You must find pertinent objects, factor them into classes
at the right granularity, define class interfaces and inheritance
hierarchies, and establish key relationships among them.
Your design should be specific to the problem at hand but
also general enough to address future problems and requirements.
You also want to avoid redesign, or at least minimize it.
Experienced object-oriented designers will tell you that
a reusable and flexible design is difficult if not impossible
to get "right" the first time. Before a design is finished,
they usually try to reuse it several times, modifying it
each time.
"Yet experienced object-oriented designers do make
good designs. Meanwhile new designers are overwhelmed by
the options available and tend to fall back on non-object-oriented
techniques they've used before. It takes a long time for
novices to learn what good object-oriented design is all
about. Experienced designers evidently know something inexperienced
ones don't. What is it?
"One thing expert designers know not to do
is solve every problem from first principles. Rather, they
reuse solutions that have worked for them in the past. When
they find a good solution, they use it again and again.
Such experience is part of what makes them experts. Consequently,
you'll find recurring patterns of classes and communicating
objects in many object-oriented systems. These patterns
solve specific design problems and make object-oriented
designs 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.
"An analogy will help illustrate the point. Novelists
and playwrights rarely design their plots from scratch.
Instead, they follow patterns like "Tragically Flawed Hero"
(Macbeth, Hamlet, etc.) or "The Romantic Novel" (countless
romance novels). In the same way, object-oriented designers
follow patterns like "represent states with objects" and
"decorate objects so you can easily add/remove features."
Once you know the pattern, a lot of design decisions follow
automatically.
"We all know the value of design experience. How many
times have you had design déjà-vuthat
feeling that you've solved a problem before but not knowing
exactly where or how? If you could remember the details
of the previous problem and how you solved it, then you
could reuse the experience instead of rediscovering it.
However, we don't do a good job of recording experience
in software design for others to use.
"The purpose of this book is to record experience
in designing object-oriented software as design patterns.
Each design pattern systematically names, explains, and
evaluates an important and recurring design in object-oriented
systems. Our goal is to capture design experience in a form
that people can use effectively. To this end we have documented
some of the most important design patterns and present them
as a catalog.
"Design patterns make it easier to reuse successful
designs and architectures. Expressing proven techniques
as design patterns makes them more accessible to developers
of new systems. Design patterns help you choose design alternatives
that make a system reusable and avoid alternatives that
compromise reusability. Design patterns can even improve
the documentation and maintenance of existing systems by
furnishing an explicit specification of class and object
interactions and their underlying intent. Put simply, design
patterns help a designer get a design "right" faster.
"None of the design patterns in this book describes
new or unproven designs. We have included only designs that
have been applied more than once in different systems. Most
of these designs have never been documented before. They
are either part of the folklore of the object-oriented community
or are elements of some successful object-oriented systemsneither
of which is easy for novice designers to learn from. So
although these designs aren't new, we capture them in a
new and accessible way: as a catalog of design patterns
having a consistent format.
"Despite the book's size, the design patterns in it
capture only a fraction of what an expert might know. It
doesn't have any patterns dealing with concurrency or distributed
programming or real-time programming. It doesn't have any
application domain-specific patterns. It doesn't tell you
how to build user interfaces, how to write device drivers,
or how to use an object-oriented database. Each of these
areas has its own patterns, and it would be worthwhile for
someone to catalog those too.
What is a design pattern?
"Christopher Alexander says, "Each pattern describes
a problem which occurs over and over again in our environment,
and then describes the core of the solution to that problem,
in such a way that you can use this solution a million times
over, without ever doing it the same way twice" [AIS+77,
page x]. Even though Alexander was talking about
patterns in buildings and towns, what he says is true about
object-oriented design patterns. Our solutions are expressed
in terms of objects and interfaces instead of walls and
doors, but at the core of both kinds of patterns is a solution
to a problem in a context.
"In general, a pattern has four essential elements:
- The pattern name is a handle we can
use to describe a design problem, its solutions, and consequences
in a word or two. Naming a pattern immediately increases
our design vocabulary. It lets us design at a higher level
of abstraction. Having a vocabulary for patterns lets
us talk about them with our colleagues, in our documentation,
and even to ourselves. It makes it easier to think about
designs and to communicate them and their trade-offs to
others. Finding good names has been one of the hardest
parts of developing our catalog.
- The problem describes when to apply
the pattern. It explains the problem and its context.
It might describe specific design problems such as how
to represent algorithms as objects. It might describe
class or object structures that are symptomatic of an
inflexible design. Sometimes the problem will include
a list of conditions that must be met before it makes
sense to apply the pattern.
- The solution describes the elements
that make up the design, their relationships, responsibilities,
and collaborations. The solution doesn't describe a particular
concrete design or implementation, because a pattern is
like a template that can be applied in many different
situations. Instead, the pattern provides an abstract
description of a design problem and how a general arrangement
of elements (classes and objects in our case) solves it.
- The consequences are the results and
trade-offs of applying the pattern. Though consequences
are often unvoiced when we describe design decisions,
they are critical for evaluating design alternatives and
for understanding the costs and benefits of applying the
pattern. The consequences for software often concern space
and time trade-offs. They may address language and implementation
issues as well. Since reuse is often a factor in object-oriented
design, the consequences of a pattern include its impact
on a system's flexibility, extensibility, or portability.
Listing these consequences explicitly helps you understand
and evaluate them.
"Point of view affects one's interpretation of what
is and isn't a pattern. One person's pattern can be another
person's primitive building block. For this book we have
concentrated on patterns at a certain level of abstraction.
Design patterns are not about designs such as linked
lists and hash tables that can be encoded in classes and
reused as is. Nor are they complex, domain-specific designs
for an entire application or subsystem. The design patterns
in this book are descriptions of communicating objects
and classes that are customized to solve a general design
problem in a particular context.
"A design pattern names, abstracts, and identifies
the key aspects of a common design structure that make it
useful for creating a reusable object-oriented design. The
design pattern identifies the participating classes and
instances, their roles and collaborations, and the distribution
of responsibilities. Each design pattern focuses on a particular
object-oriented design problem or issue. It describes when
it applies, whether it can be applied in view of other design
constraints, and the consequences and trade-offs of its
use. Since we must eventually implement our designs, a design
pattern also provides sample C++ and (sometimes) Smalltalk
code to illustrate an implementation.
"Although design patterns describe object-oriented
designs, they are based on practical solutions that have
been implemented in mainstream object-oriented programming
languages like Smalltalk and C++ rather than procedural
languages (Pascal, C, Ada) or more dynamic object-oriented
languages (CLOS, Dylan, Self). We chose Smalltalk and C++
for pragmatic reasons: Our day-to-day experience has been
in these languages, and they are increasingly popular.
"The choice of programming language is important because
it influences one's point of view. Our patterns assume Smalltalk/C++-level
language features, and that choice determines what can and
cannot be implemented easily. If we assumed procedural languages,
we might have included design patterns called "Inheritance,"
"Encapsulation," and "Polymorphism." Similarly, some of
our patterns are supported directly by the less common object-oriented
languages. CLOS has multi-methods, for example, which lessen
the need for a pattern such as Visitor (page 331). In fact,
there are enough differences between Smalltalk and C++ to
mean that some patterns can be expressed more easily in
one language than the other. (See Iterator (257) for an
example.)"
After covering the basics of design patterns, the authors
define each element that appears within a given design pattern,
so you can understand better how each one is constructed
when you look it up later in the book. Following this is
a brief description of the book's 23 design patterns: Abstract
Factory, Adapter, Bridge, Builder...all the way to Strategy,
Template Method, and Visitor. After the authors explain
how design patterns solve design problems, they explain
how to select and use (and not use) the book’s design
patterns:
How to select a design pattern
"With more than 20 design patterns in the catalog to
choose from, it might be hard to find the one that addresses
a particular design problem, especially if the catalog is
new and unfamiliar to you. Here are several different approaches
to finding the design pattern that's right for your problem:
- Consider how design patterns solve design problems.
Section 1.6 discusses how design patterns help you find
appropriate objects, determine object granularity, specify
object interfaces, and several other ways in which design
patterns solve design problems. Referring to these discussions
can help guide your search for the right pattern.
- Scan Intent sections. Section 1.4 (page 8)
lists the Intent sections from all the patterns in the
catalog. Read through each pattern's intent to find one
or more that sound relevant to your problem. You can use
the classification scheme presented in Table 1.1 (page
10) to narrow your search.
- Study how patterns interrelate. Figure 1.1
(page 12) shows relationships between design patterns
graphically. Studying these relationships can help direct
you to the right pattern or group of patterns.
- Study patterns of like purpose. The catalog
(page 79) has three chapters, one for creational patterns,
another for structural patterns, and a third for behavioral
patterns. Each chapter starts off with introductory comments
on the patterns and concludes with a section that compares
and contrasts them. These sections give you insight into
the similarities and differences between patterns of like
purpose.
- Examine a cause of redesign. Look at the causes
of redesign starting on page 24 to see if your problem
involves one or more of them. Then look at the patterns
that help you avoid the causes of redesign.
- Consider what should be variable in your design.
This approach is the opposite of focusing on the causes
of redesign. Instead of considering what might force
a change to a design, consider what you want to be able
to change without redesign. The focus here is on encapsulating
the concept that varies, a theme of many design patterns.
Table 1.2 lists the design aspect(s) that design patterns
let you vary independently, thereby letting you change
them without redesign."
|