Design Patterns: Elements of Reusable Object-Oriented Software
156
separates an object's abstraction from its implementation sothat you can vary
them independently.
Decorator (196) describes how to add responsibilitiesto objects dynamically.
Decorator is a structural pattern thatcomposes objects recursively to allow an
open-ended number ofadditional responsibilities. For example, a Decorator
objectcontaining a user interface component can add a decoration like aborder
or shadow to the component, or it can add functionality likescrolling and zooming.
We can add two decorations simply by nestingone Decorator object within another,
and so on for additionaldecorations. To accomplish this, each Decorator object
must conformto the interface of its component and must forward messages to it.The
Decorator can do its job (such as drawing a border around thecomponent) either
before or after forwarding a message.
Many structural patterns are related to some degree. We'll discussthese
relationships at the end of the chapter.
Design Patterns: Elements of Reusable Object-Oriented Software
157
Adapter
Intent
Convert the interface of a class into another interface clients expect. Adapter
lets classes work together that couldn't otherwise because of incompatible
interfaces.
Also Known As
Wrapper
Motivation
Sometimes a toolkit class that's designed for reuse isn't reusable only because
its interface doesn't match the domain-specific interface an application requires.
Consider for example a drawing editor that lets users draw and arrange graphical
elements (lines, polygons, text, etc.) into pictures and diagrams. The drawing
editor's key abstraction is the graphical object, which has an editable shape
and can draw itself. The interface for graphical objects is defined by an abstract
class called Shape. The editor defines a subclass of Shape for each kind of graphical
object: a LineShape class for lines, a PolygonShape class for polygons, and so
forth.
Classes for elementary geometric shapes like LineShape and PolygonShape are rather
easy to implement, because their drawing and editing capabilities are inherently
limited. But a TextShape subclass that can display and edit text is considerably
more difficult to implement, since even basic text editing involves complicated
screen update and buffer management. Meanwhile, an off-the-shelf user interface
toolkit might already provide a sophisticated TextView class for displaying and
editing text. Ideally we'd like to reuse TextView to implement TextShape, but
the toolkit wasn't designed with Shape classes in mind. So we can't use TextView
and Shape objects interchangeably.
How can existing and unrelated classes like TextView work in an application that
expects classes with a different and incompatible interface? We could change the
TextView class so that it conforms to the Shape interface, but that isn't an option
unless we have the toolkit's source code. Even if we did, it wouldn't make sense
to change TextView; the toolkit shouldn't have to adopt domain-specific interfaces
just to make one application work.
Do'stlaringiz bilan baham: |