KEMBAR78
Software and architecture design pattern | PDF
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 61
Design Pattern Catalog
Structural Patterns
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.
Module 2
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 62
Meanwhile, an off-the-shelf user interface toolkit might already provide a sophisticated
TextView class for displaying and editing text.
This diagram illustrates the object adapter case. It shows how BoundingBox requests,
declared in class Shape, are converted to GetExtent requests defined in TextView.
Since TextShape adapts TextView to the Shape interface, the drawing editor can reuse the
otherwise incompatible TextView class.
Applicability
Use the Adapter pattern when
• you want to use an existing class, and its interface does not match the one you need.
• you want to create a reusable class that cooperates with unrelated or unforeseen
classes, that is, classes that don't necessarily have compatible interfaces.
• (object adapter only) you need to use several existing subclasses, but it's unpractical to
adapt their interface by subclassing every one. An object adapter can adapt the interface of its
parent class
Structure
A class adapter uses multiple inheritance to adapt one interface to another:
An object adapter relies on object composition:
Participants
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 63
• Target (Shape) - defines the domain-specific interface that Client uses.
• Client (DrawingEditor) – collaborates with objects conforming to the Target interface.
• Adaptec (TextView) - defines an existing interface that needs adapting.
• Adapter (TextShape) - adapts the interface of Adaptec to the Target interface.
Collaborations
• Clients call operations on an Adapter instance. In turn, the adapter calls Adaptec operations
that carry out the request.
Consequences
Class and object adapters have different trade-offs. A class adapter
• adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a
class adapter won't work when we want to adapt a class and all its subclasses.
• lets Adapter override some of Adaptee's behavior, since Adapter is a subclass of Adaptee.
• introduces only one object, and no additional pointer indirection is needed to get to the
adaptee.
An object adapter
• Lets a single Adapter work with many Adaptees—that is, the Adaptee itself and all of its
subclasses (if any). The Adapter can also add functionality to all Adaptees at once.
• Makes it harder to override Adaptee behavior. It will require subclassing Adaptee and
making Adapter refer to the subclass rather than the Adaptee itself.
Here are other issues to consider when using the Adapter pattern:
1. How much adapting does Adapter do? Adapters vary in the amount of work they do to
adapt Adaptee to the Target interface. There is a spectrum of possible work, from simple
interface conversion—for example, changing the names of operations—to supporting an
entirely different set of operations. The amount of work Adapter does depends on how
similar the Target interface is to Adaptee's.
2. Pluggable adapters. A class is more reusable when you minimize the assumptions other
classes must make to use it. By building interface adaptation into a class, you eliminate the
assumption that other classes see the same interface. Put another way, interface adaptation
lets us incorporate our class into existing systems that might expect different interfaces to the
class. Object WorksSmalltalk [Par90] uses the term pluggable adapter to describe classes
with built-in interface adaptation.
3. Using two-way adapters to provide transparency. A potential problem with adapters is that
they aren't transparent to all clients. An adapted object no longer conforms to the Adaptec
interface, so it can't be used as is wherever an Adaptec object can. Two-way adapters can
provide such transparency. Specifically, they're useful when two different clients need to
view an object differently.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 64
Consider the two-way adapter that integrates Unidraw, a graphical editor framework [VL90],
and QOCA, a constraint-solving toolkit [HHMV92]. Both systems have classes that represent
variables explicitly: Unidraw has StateVariable, and QOCA has ConstraintVariable. To make
Unidraw work with QOCA, ConstraintVariable must be adapted to StateVariable; to let
QOCA propagate solutions to Unidraw, StateVariable must be adapted to ConstraintVariable
The solution involves a two-way class adapter ConstraintStateVariable, a subclass of both
StateVariable and ConstraintVariable that adapts the two interfaces to each other. Multiple
inheritance is a viable solution in this case because the interfaces of the adapted classes are
substantially different. The two-way class adapter conforms to both of the adapted classes
and can work in either system.
Implementation
Although the implementation of Adapter is usually straightforward, here are some issues to
keep in mind:
1. Implementing class adapters in C++.In a C++ implementation of a class adapter, Adapter
would inherit publicly from Target and privately from Adaptec. Thus Adapter would be a
subtype of Target but not of Adaptec.
2. Pluggable adapters. Let's look at three ways to implement pluggable adapters for the
TreeDisplay widget described earlier, which can lay out and display a hierarchical structure
automatically. The first step, which is common to all three of the implementations discussed
here, is to find a "narrow" interface for Adaptec, that is, the smallest subset of operations that
lets us do the adaptation. A narrow interface consisting of only a couple of operations is
easier to adapt than an interface with dozens of operations. For TreeDisplay, the adaptee is
any hierarchical structure. A minimalist interface might include two operations, one that
defines how to present a node in the hierarchical structure graphically, and another that
retrieves the node's children.
The narrow interface leads to three implementation approaches:
(a) Using abstract operations. Define corresponding abstract operations for the narrow
Adaptee interface in the TreeDisplay class. Subclasses must implement the abstract
operations and adapt the hierarchically structured object. For example, a
DirectoryTreeDisplay subclass will implement these operations by accessing the directory
structure.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 65
(b) Using delegate objects. In this approach, TreeDisplay forwards requests for accessing the
hierarchical structure to a delegate object. TreeDisplay can use a different adaptation strategy
by substituting a different delegate.
For example, suppose there exists a DirectoryBrowser that uses a TreeDisplay.
DirectoryBrowser might make a good delegate for adapting TreeDisplay to the hierarchical
directory structure. In dynamically typed languages like Smalltalk or Objective C, this
approach only requires an interface for registering the delegate with the adapter. Then
TreeDisplay simply forwards the requests to the delegate. NEXTSTEP [Add94] uses this
approach heavily to reduce subclassing.
(c) Parameterized adapters. The usual way to support pluggable adapters in Smalltalk is to
parameterize an adapter with one or more blocks. The block construct supports adaptation
without subclassing. A block can adapt a request, and the adapter can store a block for each
individual request. In our example, this means TreeDisplay stores one block for converting a
node into a GraphicNode and another block for accessing a node's children.
Known Uses
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 66
The Motivation example comes from ET++Drawing Editor.
Related Patterns
Bridge has a structure similar to an object adapter, but Bridge has a different intent: It is
meant to separate an interface from its implementation so that they can be varied easily and
independently. An adapter is meant to change the interface of an existing object.
Decorator enhances another object without changing its interface. A decorator is thus more
transparent to the application than an adapter is. As a consequence, Decorator supports
recursive composition, which isn't possible with pure adapters.
Proxy defines a representative or surrogate for another object and does not change its
interface.
BRIDGE
Intent
Decouple an abstraction from its implementation so that the two can vary independently.
Also Known As
Handle/Body
Motivation
* When an abstraction can have one of several possible implementations, the usual way to
accommodate them is to use inheritance.
* An abstract class defines the interface to the abstraction, and concrete subclasses implement
it in different ways.
* But this approach isn't always flexible enough. Inheritance binds an implementation to the
abstraction permanently, which makes it difficult to modify, extends and reuse abstractions
and implementations independently.
Consider the implementation of a portable Window abstraction in a user interface toolkit.
This abstraction should enable us to write applications that work on both the XWindow
System and IBM's Presentation Manager (PM), for example. Using inheritance, we could
define an abstract class Window and subclasses Xwindow and PMWindow that implement
the Window interface for the different platforms.
But this approach has two drawbacks:
1. It's inconvenient to extend the Window abstraction to cover different kinds of
windows or new platforms. Imagine an IconWindow subclass of Window that
specializes the Window abstraction for icons . To support IconWindows for both
platforms, we have to implement two new classes, XlconWindow and
PMIconWindow.
2. It makes client code platform-dependent.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 67
* The Bridge pattern addresses these problems by putting the Window abstraction and its
implementation in separate class hierarchies.
* There is one class hierarchy for window interfaces (Window, IconWindow,
TransientWindow) and a separate hierarchy for platform-specific window implementations,
with Windowlmp as its root. The XWindowImp subclass, for example, provides an
implementation basedon the XWindow System.
Applicability
Use the Bridge pattern when
• you want to avoid a permanent binding between an abstraction and its implementation. This
might be the case, for example, when the implementation must be selected or switched at run-
time.
• both the abstractions and their implementations should be extensible by subclassing. In this
case, the Bridge pattern lets you combine the different abstractions and implementations and
extend them independently.
• changes in the implementation of an abstraction should have no impact on clients; that is,
their code should not have to be recompiled.
• (C++) you want to hide the implementation of an abstraction completely from clients. In
C++ the representation of a class is visible in the class interface.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 68
• you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a
class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the
term "nested generalizations" [RBP+91] to refer to such class hierarchies.
• you want to share an implementation among multiple objects(perhaps using reference
counting), and this fact should be hidden from the client. A simple example is Coplien's
String class, in which multiple objects can share the same string representation (StringRep).
Structure
Participants
• Abstraction (Window) - defines the abstraction's interface. - maintains a reference to an
object of type Implementor.
• RefmedAbstraction (IconWindow) – Extends the interface defined by Abstraction.
• Implementor (Windowlmp) - defines the interface for implementation classes. This
interface doesn't have to correspond exactly to Abstraction's interface; in fact the two
interfaces can be quite different. Typically the Implementor interface provides only primitive
operations, and Abstraction defines higher-level operations based on these primitives.
• Concretelmplementor (XWindowImp, PMWindowImp) - implements the Implementor
interface and defines its concrete implementation.
Collaborations
• Abstraction forwards client requests to its Implementor object.
Consequences
The Bridge pattern has the following consequences:
1. Decoupling interface and implementation. An implementation is not bound permanently to
an interface. The implementation of an abstraction can be configured at run-time. It's even
possible for an object to change its implementation at run-time. Decoupling Abstraction and
Implementor also eliminates compile-time dependencies on the implementation. Changing an
implementation class doesn't require recompiling the Abstraction class and its clients. This
property is essential when you must ensure binary compatibility between different versions of
a class library. Furthermore, this decoupling encourages layering that can lead to a better
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 69
structured system. The high-level part of a system only has to know about Abstraction and
Implementor.
2. Improved extensibility. You can extend the Abstraction and Implementor hierarchies
independently.
3. Hiding implementation details from clients. You can shield clients from implementation
details, like the sharing of implementor objects and the accompanying reference count
mechanism (if any).
Implementation
Consider the following implementation issues when applying the Bridge pattern:
1. Only one Implementor. In situations where there's only one implementation, creating an
abstract Implementor class isn't necessary. This is a degenerate case of the Bridge pattern;
there's a one-to-one relationship between Abstraction and Implementor. Nevertheless, this
separation is still useful when a change in the implementation of a class must not affect its
existing clients— that is, they shouldn't have to be recompiled just relinked.
2. Creating the right Implementor object.
How, when, and where do you decide which Implementor class to instantiate when there's
more than one?
If Abstraction knows about all Concretelmplementor classes, then it can instantiate one of
them in its constructor; it can decide between them based on parameters passed to its
constructor. If, for example, a collection class supports multiple implementations, the
decision can be based on the size of the collection. A linked list implementation can be used
for small collections and a hash table for larger ones.
Another approach is to choose a default implementation initially and change it later according
to usage. For example, if the collection grows bigger than a certain threshold, then it switches
its implementation to one that's more appropriate for a large number of items
3. Sharing implementors.
Coplien illustrates how the Handle/Body idiom in C++ can be used to share implementations
among several objects [Cop92]. The Body stores a reference count that the Handle class
increments and decrements. The code for assigning handles with shared bodies has the
following general form:
4. Using multiple inheritance.
You can use multiple inheritance in C++ to combine an interface with its implementation .For
example, a class can inherit publicly from Abstraction and privately from a Concretelmplementor. But
because this approach relies on static inheritance, it binds an implementation permanently to its
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 70
interface. Therefore you can't implement a true Bridge with multiple inheritances—at least not in
C++.
Known Uses
The Window example above comes from ET++ [WGM88]. In ET++, Windowlmp is called
"WindowPort" and has subclasses such as XWindowPortand SunWindowPort. The Window
object creates its corresponding Implementor object by requesting it from an abstract factory
called "WindowSystem." WindowSystem provides an interface for creating platform-specific
objects such as fonts, cursors, bitmaps, and so forth.
The ET++ Window/WindowPort design extends the Bridge pattern in that the WindowPort
also keeps a reference back to the Window. The WindowPort implementor class uses this
reference to notify Window about WindowPort-specific events: the arrival of input events,
window resizes, etc.
Related Patterns
An Abstract Factory can create and configure a particular Bridge.
The Adapter pattern is geared toward making unrelated classes work together. It is usually
applied to systems after they're designed. Bridge, on the other hand, is used up-front in a
design to let abstractions and implementations vary independently.
COMPOSITE
Intent
Compose objects into tree structures to represent part-whole hierarchies. Composite lets
clients treat individual objects and compositions of objects uniformly.
Motivation
Graphics applications like drawing editors and schematic capture systems let users build
complex diagrams out of simple components. The user can group components to form larger
components, which in turn can be grouped to form still larger components.
A simple implementation could define classes for graphical primitives such as Text and Lines
plus other classes that act as containers for these primitives.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 71
The key to the Composite pattern is an abstract class that represents both primitives and their
containers. For the graphics system, this class is Graphic.
Graphic declares operations like Draw that are specific to graphical objects. It also declares
operations that all composite objects share, such as operations for accessing and managing its
children.
The following diagram shows a typical composite object structure of recursively composed
Graphic objects:
Applicability
Use the Composite pattern when
• you want to represent part-whole hierarchies of objects.
• you want clients to be able to ignore the difference between compositions of objects and
individual objects. Clients will treat all objects in the composite structure uniformly.
Structure
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 72
A typical Composite object structure might look like this:
Participants
• Component (Graphic)
- declares the interface for objects in the composition.
- Implements default behavior for the interface common to all classes, as appropriate.
- declares an interface for accessing and managing its child components.
- (optional) defines an interface for accessing a component's parent in the recursive structure,
and implements it if that's appropriate.
• Leaf (Rectangle, Line, Text, etc.)
- represents leaf objects in the composition. A leaf has no children.
- defines behavior for primitive objects in the composition.
• Composite (Picture)
- defines behavior for components having children.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 73
- stores child components.
- implements child-related operations in the Component interface.
• Client
- manipulates objects in the composition through the Component interface.
Collaborations
• Clients use the Component class interface to interact with objects in the composite
structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a
Composite, then it usually forwards requests to its child components, possibly performing
additional operations before and/or after forwarding
Consequences
The Composite pattern
• defines class hierarchies consisting of primitive objects and composite objects. Primitive
objects can be composed into more complex objects, which in turn can be composed, and so
on recursively. Wherever client code expects a primitive object, it can also take a composite
object.
• makes the client simple. Clients can treat composite structures and individual objects
uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a
leaf or a composite component. This simplifies client code, because it avoids having to write
tag-and-case-statement-style functions over the classes that define the composition.
• makes it easier to add new kinds of components. Newly defined Composite or Leaf
subclasses work automatically with existing structures and client code. Clients don't have to
be changed for new Component classes. • can make your design overly general. The
disadvantage of making it easy to add new components is that it makes it harder to restrict the
components of a composite. Sometimes you want a composite to have only certain
components. With Composite, you can't rely on the type system to enforce those constraints
for you. You'll have to use run-time checks instead.
Implementation
There are many issues to consider when implementing the Composite pattern:
1. Explicit parent references. Maintaining references from child components to their parent
can simplify the traversal and management of a composite structure. The parent reference
simplifies moving up the structure and deleting a component. Parent references also help
support the Chain of Responsibility pattern.
2. Sharing components. It's often useful to share components, for example, to reduce storage
requirements. Butwhen a component can have no more than one parent, sharing components
becomes difficult.
3. Maximizing the Component interface. One of the goals of the Composite pattern is to make
clients unaware of the specific Leaf or Composite classes they're using. To attain this goal,
the Component class should define as many common operations for Composite and Leaf
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 74
classes as possible. The Component class usually provides default implementations for these
operations, and Leaf and Composite subclasses will override them.
However, this goal will sometimes conflict with the principle of class hierarchy design that
says a class should only define operations that are meaningful to its subclasses. There are
many operations that Component supports that don't seem to make sense for Leaf classes.
4. Declaring the child management operations. Although the Composite class implements the
Add and Remove operations for managing children, an important issue in the Composite
pattern is which classes declare these operations in the Composite class hierarchy. Should we
declare these operations in the Component and make them meaningful for Leaf classes, or
should we declare and define them only in Composite and its subclasses?
The decision involves a trade-off between safety and transparency:
• Defining the child management interface at the root of the class hierarchy gives you
transparency, because you can treat all components uniformly. It costs you safety, however,
because clients may try to do meaningless things like add and remove objects from leaves.
• Defining child management in the Composite class gives you safety, because any attempt to
add or remove objects from leaves will be caught at compile-time in a statically typed
language like C++. But you lose transparency, because leaves and composites have different
interfaces.
One approach isto declare an operation Composite* GetComposite ( ) in the Component
class. Component provides a default operation that returns a null pointer. The Composite
class redefines this operation to return itself through the pointer:
GetComposite lets you query a component to see if it's a composite.You can perform Add
and Remove safely on the composite it returns.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 75
5. Should Component implement a list of Components? You might be tempted to define the
set of children as an instance variable in the Component class where the child access and
management operations are declared. But putting the child pointer in the base class incurs a
space penalty for every leaf, even though a leaf never has children. This is worthwhile only if
there are relatively few children in the structure.
6. Child ordering. Many designs specify an ordering on the children of Composite. In the
earlier Graphics example, ordering may reflect front-to-back ordering. If Composites
represent parse trees, then compound statements can be instances of a Composite whose
children must be ordered to reflect the program. When child ordering is an issue, you must
design child access and management interfaces carefully to manage the sequence of children.
The Iterator pattern can guide you in this.
7. Caching to improve performance. If you need to traverse or search compositions
frequently, the Composite class can cache traversal or search information about its children.
The Composite can cache actual results or just information that lets it short-circuit the
traversal or search. For example, the Picture class from the Motivation example could cache
the bounding box of its children. During drawing or selection, this cached bounding box lets
the Picture avoid drawing or searching when its children aren't visible in the current window.
Changes to a component will require invalidating the caches of its parents. This works best
when components know their parents. So if you're using caching, you need to define an
interface for telling composites that their caches are invalid.
8. Who should delete components? In languages without garbage collection, it's usually best
to make a Composite responsible for deleting its children when it's destroyed. An exception
to this rule is when Leaf objects are immutable and thus can be shared.
9. What's the best data structure for storing components? Composites may use a variety of
data structures to store their children, including linked lists, trees, arrays, and hash tables. The
choice of data structure depends (as always) on efficiency.
Known Uses
The RTL Smalltalk compiler framework [JML92] uses the Composite pattern extensively.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 76
Related Patterns
Often the component-parent link is used for a Chain of Responsibility.
Decorator is often used with Composite. When decorators and composites are used together,
they will usually have a common parent class. So decorators will have to support the
Component interface with operations like Add, Remove, and GetChild.
Flyweight lets you share components, but they can no longer refer to their parents.
Iterator can be used to traverse composites.
Visitor localizes operations and behavior that would otherwise be distributed across
Composite and Leaf classes.
DECORATOR
Intent
* Attach additional responsibilities to an object dynamically. Decorators provide a flexible
alternative to subclassing for extending functionality.
Also Known As
Wrapper
Motivation
* Sometimes we want to add responsibilities to individual objects, not to an entire class.
A graphical user interface toolkit, for example, should let you add properties like borders or
behaviors like scrolling to any user interface component.
One way to add responsibilities is with inheritance. Inheriting a border from another class
puts a border around every subclass instance.
This is inflexible, however, because the choice of border is made statically.
A client can't control how and when to decorate the component with a border.
A more flexible approach is to enclose the component in another object that adds the border.
The enclosing object is called a decorator.
The decorator conforms to the interface of the component it decorates so that its presence is
transparent to the component's clients.
The decorator forwards requests to the component and may perform additional actions (such
as drawing a border) before or after forwarding. Transparency lets you nest decorators
recursively, thereby allowing an unlimited number of added responsibilities
For example, suppose we have a TextView object that displays text in a window.
TextView has no scroll bars by default, because we might not always need them. When we
do, we can use a ScrollDecorator to add them.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 77
Suppose we also want to add a thick black border around the TextView. We can use a
BorderDecorator to add this as well.
We simply compose the decorators with the TextView to produce the desired result
The ScrollDecorator and BorderDecorator classes are subclasses of Decorator, an abstract
class for visual components that decorate other visual components.
* VisualComponent is the abstract class for visual objects. It defines their drawing and event
handling interface.
* Decorator subclasses are free to add operations for specific functionality. For example,
ScrollDecorator's ScrollTo operation lets other objects scroll the interface if they know there
happens to be a ScrollDecorator object in the interface.
Applicability
Use Decorator
• to add responsibilities to individual objects dynamically and transparently, that is,
without affecting other objects.
• for responsibilities that can be withdrawn.
• when extension by subclassing is impractical. Sometimes a large number of
independent extensions are possible and would produce an explosion of subclasses to
support every combination.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 78
Structure
Participants
• Component (VisualComponent)
- defines the interface for objects that can have responsibilities added to them dynamically.
• ConcreteComponent (TextView)
- defines an object towhich additional responsibilities canbe attached.
• Decorator
- maintains a reference to a Component object and defines an interface that conforms to
Component's interface.
• ConcreteDecorator (BorderDecorator, ScrollDecorator)
- adds responsibilities to the component.
Collaborations
• Decorator forwards requests to its Component object. It may optionally perform additional
operations before and after forwarding the request.
Consequences
The Decorator pattern has at least two key benefits and two liabilities:
1. More flexibility than static inheritance. The Decorator pattern provides a more flexible
way to add responsibilities to objects than can be had with static (multiple) inheritance. With
decorators, responsibilities can be added and removed at run-time simply by attaching and
detaching them. In contrast, inheritance requires creating a new class for each additional
responsibility (e.g., BorderedScrollableTextView, BorderedTextView). This gives rise to
many classes and increases the complexity of a system. Furthermore, providing different
Decorator classes for a specific Component class lets you mix and match responsibilities
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 79
2. Avoids feature-laden classes high up in the hierarchy. Decorator offers a payas-you-go
approach to adding responsibilities. Instead of trying to support all foreseeable features in a
complex, customizable class, you can define a simple class and add functionality
incrementally with Decorator objects. Functionality can be composed from simple pieces. As
a result, an application needn't pay for features it doesn't use. It's also easy to define new
kinds of Decorators independently from the classes of objects they extend, even for
unforeseen extensions. Extending a complex class tends to expose details unrelated to the
responsibilities you're adding.
3. A decorator and its component aren't identical. A decorator acts as a transparent enclosure.
But from an object identity point of view, a decorated component is not identical to the
component itself. Hence you shouldn't rely on object identity when you use decorators.
4. Lots of little objects. A design that uses Decorator often results in systems composed of
lots of little objects that all look alike. The objects differ only in the way they are
interconnected, not in their class or in the value of their variables. Although these systems are
easy to customize by those who understand them, they can be hard to learn and debug.
Implementation
Several issues should be considered when applying the Decorator pattern:
1. Interface conformance. A decorator object's interface must conform to the interface of the
component it decorates. ConcreteDecorator classes must therefore inherit from a common
class (at least in C++).
2. Omitting the abstract Decorator class. There's no need to define an abstract Decorator
class when you only need to add one responsibility. That's often the case when you're dealing
with an existing class hierarchy rather than designing a new one. In that case, you can merge
Decorator's responsibility for forwarding requests to the component into the
ConcreteDecorator.
3. Keeping Component classes lightweight. To ensure a conforming interface, components
and decorators must descend from a common Component class. It's important to keep this
common class lightweight; that is, it should focus on defining an interface, not on storing
data. The definition of the data representation should be deferred to subclasses; otherwise the
complexity of the Component class might make the decorators too heavyweight to use in
quantity. Putting a lot of functionality into Component also increases the probability that
concrete subclasses will pay for features they don't need.
4. Changing the skin of an object versus changing its guts. We can think of a decorator as a
skin over an object that changes its behavior. An alternative is to change the object's guts.
The Strategy pattern is a good example of a pattern for changing the guts.
For example, we can support different border styles by having the component defer border-
drawing to a separate Border object. The Border object is a Strategy object that encapsulates
a border-drawing strategy. By extending the number of strategies from just one to an open-
ended list, we achieve the same effect as nesting decorator recursively.
In MacApp 3.0 and Bedrock, for example, graphical components (called "views") maintain a
list of "adorner" objects that can attach additional adornments like borders to a view
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 80
component. If a view has any adorners attached, then it gives them a chance to draw
additional embellishments. MacApp and Bedrock must use this approach because the
Viewclass is heavyweight. It would be too expensive to use a full-fledged View just to add a
border.
Since the Decorator pattern only changes a component from the outside, the component
doesn't have to know anything about its decorators; that is, the decorators are transparent to
the component:
With strategies, the component itself knows about possible extensions. So it has to reference
and maintain the corresponding strategies:
Known Uses
Many object-oriented user interface toolkits use decorators to add graphical embellishments
to widgets. Examples include Interviews [LVC89, LCI+92], ET++ [WGM88], and the Object
WorksSmalltalkclass library [Par90]. More exotic applications of Decorator are the
DebuggingGlyph from Interviews and the PassivityWrapper from ParcPlace Smalltalk.
Streams are a fundamentalabstractionin most I/O facilities. Astream can provide an interface
for converting objects into a sequence of bytes or characters. That lets us transcribe an object
to a file or to a string in memory for retrieval later. A straightforward way to do this is to
define an abstractStream class with subclasses MemoryStream and FileStream. But suppose
we also want to be able to do the following:
• Compress the stream data using different compression algorithms (runlength encoding,
Lempel-Ziv, etc.).
• Reduce the stream data to 7-bit ASCII characters so that it can be transmitted over an ASCII
communication channel.
The Decorator pattern gives us an elegant way to add these responsibilities to streams. The
diagram below shows one solution to the problem:
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 81
For example, the CompressingStream subclass compresses the data, and the ASCII7Stream
converts the data into 7-bit ASCII. Now, to create a FileStream that compresses its data and
converts the compressed binary data to 7-bitASCII, we decorate a FileStream with a
CompressingStream and an ASCII7Stream:
Related Patterns
Adapter: A decorator is different from an adapter in that a decorator only changes an object's
responsibilities, not its interface; an adapter will give an object a completely new interface.
Composite A decorator can be viewed as a degenerate composite with only one component.
However, a decorator adds additional responsibilities—it isn't intended for object
aggregation.
Strategy: A decorator lets you change the skin of an object; a strategy lets you change the
guts. These are two alternative ways of changing an object.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 82
FACADE
Intent
Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level
interface that makes the subsystem easier to use.
Motivation
Structuring a system into subsystems helps reduce complexity. A common design goal is to
minimize the communication and dependencies between subsystems.
One way to achieve this go al is to introduce a facade object that provides a single, simplified
interface to the more general facilities of a subsystem.
This subsystem contains classes such as Scanner, Parser, ProgramNode, BytecodeStream, and
Program NodeBuilder that implement the compiler. To provide a higher-level interface that
can shield clients from these classes, the compiler subsystem also includes a Compiler class.
This class defines a unified interface to the compiler's functionality.
The Compiler class acts as a facade: It offers clients a single, simple interface to the compiler
subsystem
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 83
Applicability
Use the Façade pattern when
• you want to provide a simple interface to a complex subsystem
• there are many dependencies between clients and the implementation classes of an
abstraction.
• you want to layer your subsystems.
Structure
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 84
Participants
• Facade (Compiler)
- knows which subsystem classes are responsible for a request. - delegates client requests to
appropriate subsystem objects.
• Subsystem classes (Scanner, Parser, ProgramNode, etc.)
- implement subsystem functionality.
- handle work assigned by the Facade object.
- have no knowledge of the facade; that is, they keep no references to it.
Collaborations
• Clients communicate with the subsystem by sending requests to Facade, which forwards
them to the appropriate subsystem object(s). Although the subsystem objects perform the
actual work, the facade may have to do work of its own to translate its interface to subsystem
interfaces.
• Clients that use the facade don't have to access its subsystem objects directly.
Consequences
The Facade pattern offers the following benefits:
1. It shields clients from subsystem components, thereby reducing the number of objects that
clients deal with and making the subsystem easier to use.
2. It promotes weak coupling between the subsystem and its clients. Often the components in
a subsystem are strongly coupled. Weak coupling lets you vary the components of the
subsystem without affecting its clients. Facades help layer a system and the dependencies
between objects. They can eliminate complex or circular dependencies. This can be an
important consequence when the client and the subsystem are implemented independently.
3. It doesn't prevent applications from using subsystem classes if they need to. Thus you can
choose between ease of use and generality.
Implementation
Consider the following issues when implementing a facade:
1. Reducing client-subsystem coupling. The coupling between clients and the subsystem can
be reduced even further by making Facade an abstract class with concrete subclasses for
different implementations of a subsystem. Then clients can communicate with the subsystem
through the interface of the abstract Facade class. This abstract coupling keeps clients from
knowing which implementation of a subsystem is used.
An alternative to subclassing is to configure a Facade object with different subsystem objects.
To customize the facade, simply replace one or more of its subsystem objects.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 85
2. Public versus private subsystem classes. A subsystem is analogous to a class in that both
have interfaces, and both encapsulate something—a class encapsulates state and operations,
while a subsystem encapsulates classes. And just as it's useful to think of the public and
private interface of a class, we can think of the public and private interface of a subsystem.
The public interface to a subsystem consists of classes that all clients can access; the
private interface is just for subsystem extenders. For example, the classes Parser and Scanner
in the compiler subsystem are part of the public interface
Known Uses
The compiler example in the Sample Code section was inspired by the Object
WorksSmalltalk compiler system
In the ET++ application framework [WGM88], an application can have built-in browsing
tools for inspecting its objects at run-time. These browsing tools are implemented in a
separate subsystem that includes a Facade class called "ProgrammingEnvironment." This
facade defines operations such as InspectObject and InspectClass for accessing the browsers.
The Choices operating system [CIRM93] uses facades to compose many frameworks into
one. The key abstractions in Choices are processes, storage, and address spaces. For each of
these abstractions there is a corresponding subsystem, implemented as a framework, that
supports porting Choices to a variety of different hardware platforms. Two of these
subsystems have a "representative" (i.e., facade). These representatives are
FileSystemlnterface (storage) and Domain (address spaces).
For example, the virtual memory framework has Domain as its facade. A Domain represents
an address space. It provides a mapping between virtual addresses and offsets into memory
objects, files, or backing store. The main operations on Domain support adding a memory
object at a particular address, removing a memory object, and handling a page fault.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 86
As the preceding diagram shows, the virtual memory subsystem uses the following
components internally:
 MemoryObject represents a data store.
 MemoryObjectCache caches the data of MemoryObjects in physical memory.
MemoryObjectCache is actually a Strategy that localizes the caching policy.
 AddressTranslation encapsulates the address translation hardware.
Related Patterns
Abstract Factory can be used with Facade to provide an interface for creating subsystem
objects in a subsystem-independent way. Abstract Factory can also be used as an alternative
to Facade to hide platform-specific classes.
Mediator is similar to Facade in that it abstracts functionality of existing classes. However,
Mediator's purpose is to abstract arbitrary communication between colleague objects, often
centralizing functionality that doesn't belong in any one of them. A mediator's colleagues are
aware of and communicate with the mediator instead of communicating with each other
directly. In contrast, a facade merely abstracts the interface to subsystem objects to make
them easier to use; it doesn't define new functionality, and subsystem classes don't know
about it.
Usually only one Facade object is required. Thus Facade objects are often Singletons.
FLYWEIGHT
Intent
Use sharing to support large numbers of fine-grained objects efficiently.
Motivation
Some applications could benefit from using objects throughout their design, but a naive
implementation would be prohibitively expensive.
* Most document editor implementations have text formatting and editing facilities that are
modularized to some extent. Object-oriented document editors typically use objects to
represent embedded elements like tables and figures.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 87
The drawback of such a design is its cost. Even moderate-sized documents may require
hundreds of thousands of character objects, which will consume lots of memory and may
incur unacceptable run-time overhead.
A flyweight is a shared object that can be used in multiple contexts simultaneously.
The flyweight acts as an independent object in each context—it's indistinguishable from an
instance of the object that's not shared. Flyweights cannot make assumptions about the
context in which they operate.
The key concept here is the distinction between intrinsic and extrinsic state.
Intrinsic state is stored in the flyweight; it consists of information that's independent of the
flyweight's context, thereby making it sharable.
Extrinsic state depends on and varies with the flyweight‗s context and therefore can't be
shared. Client objects are responsible for passing extrinsic state to the flyweight when it
needs it.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 88
A flyweight representing the letter "a" only stores the corresponding character code; it doesn't
need to store its location or font. Clients supply the context dependent information that the
flyweight needs to draw itself.
For example, a Row glyph knows where its children should draw themselves so that they are
tiled horizontally.
Applicability
The Flyweight pattern's effectiveness depends heavily on how and where it's used.
• An application uses a large number of objects.
• Storage costs are high because of the rapid quantity of objects.
• Most object state can be made extrinsic
• The application doesn't depend on object identity
Structure
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 89
Participants
Flyweight (Glyph)
- declares an interface through which flyweights can receive and act on extrinsic state.
• ConcreteFlyweight (Character)
- implements the Flyweight interface and adds storage for intrinsic state, if any. A
ConcreteFlyweight object must be sharable. Any state it stores must be intrinsic; that is, it
must be independent of the ConcreteFlyweight object's context.
• UnsharedConcreteFlyweight (Row, Column)
- not all Flyweight subclasses need to be shared. The Flyweight interface enables sharing; it
doesn't enforce it. It's common for UnsharedConcreteFlyweight objects to have
ConcreteFlyweight objects as children at some level in the flyweight object structure (as the
Row and Column classes have).
• FlyweightFactory
- creates and manages flyweight objects.
- ensures that flyweights are shared properly. When a client requests a flyweight, the
FlyweightFactory object supplies an existing instance or creates one, if none exists.
• Client
- maintains a reference to flyweight(s).
- computes or stores the extrinsic state of flyweight(s).
Collaborations
• State that a flyweight needs to function must be characterized as either intrinsic or extrinsic.
Intrinsic state is stored in the ConcreteFlyweight object; extrinsic state is stored or computed
by Client objects. Clients pass this state to the flyweight when they invoke its operations.
• Clients should not instantiate ConcreteFlyweights directly. Clients must obtain
ConcreteFlyweight objects exclusively from the FlyweightFactory object to ensure they are
shared properly.
Consequences
Flyweights may introduce run-time costs associated with transferring, finding, and/or
computing extrinsic state, especially if it was formerly stored as intrinsic state. However,
such costs are offset by space savings, which increase as more flyweights are shared. Storage
savings are a function of several factors:
• the reduction in the total number of instances that comes from sharing
• the amount of intrinsic state per object
• whether extrinsic state is computed or stored
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 90
Implementation
Consider the following issues when implementing the Flyweight pattern:
1. Removing extrinsic state. The pattern's applicability is determined largely by how easy it is
to identify extrinsic state and remove it from shared objects. Removing extrinsic state won't
help reduce storage costs if there are as many different kinds of extrinsic state as there are
objects before sharing. Ideally, extrinsic state can be computed from a separate object
structure, one with far smaller storage requirements.
In our document editor, for example, we can store a map of typographic information
in a separate structure rather than store the font and type style with each character object. The
map keeps track of runs of characters with the same typographic attributes. When a character
draws itself, it receives its typographic attributes as a side-effect of the draw traversal.
Because documents normally use just a few different fonts and styles, storing this information
externally to each character object is far more efficient than storing it internally.
2. Managing shared objects. Because objects are shared, clients shouldn't instantiate them
directly. FlyweightFactory lets clients locate a particular flyweight. FlyweightFactory objects
often use an associative store to let clients look up flyweights of interest. For example, the
flyweight factory in the document editor example can keep a table of flyweights indexed by
character codes. The manager returns the proper flyweight given its code, creating the
flyweight if it does not already exist.
Known Uses
ET++ [WGM88] uses flyweights to support look-and-feel independence. The look-and-feel
standard affects the layout of user interface elements (e.g., scroll bars, buttons, menus—
known collectively as "widgets") and their decorations (e.g., shadows, beveling). A widget
delegates all its layout and drawing behavior to a separate Layout object. Changing the
Layout object changes the look and feel, even at run-time.
The Layout objects are created and managed by Look objects. The Look class is an Abstract
Factory that retrieves a specific Layout object with operations like GetButtonLayout,
GetMenuBarLayout, and so forth. For each look-and-feel standard there is a corresponding
Looksubclass (e.g., MotifLook, OpenLook)that supplies the appropriate Layoutobjects.
By the way, Layout objects are essentially strategies (see Strategy). They are an
example of a strategy object implemented as a flyweight.
Related Patterns
The Flyweight pattern is often combined with the Composite pattern to implement a logically
hierarchical structure in terms of a directed-acyclic graph with shared leaf nodes.
It's often best to implement State and Strategy objects as flyweights.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 91
PROXY
Intent
Provide a placeholder for another object to control access to it.
Also Known As
Surrogate
Motivation
Consider a document editor that can embed graphical objects in a document. Some graphical
objects, like large raster images, can be expensive to create. But opening a document should
be fast, so we should avoid creating all the expensive objects at once when the document is
opened. This isn't necessary anyway, because not all of these objects will be visible in the
document at the same time.
The image proxy creates the real image only when the document editor asks it to display
itself by invoking its Draw operation. The proxy forwards subsequent requests directly to the
image. It must therefore keep a reference to the image after creating it
Applicability
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 92
1. A remote proxy provides a local representative for an object in a different address
space
2. A virtual proxy creates expensive objects on demand.
3. A protection proxy controls access to the original object
4. A smart reference is a replacement for a bare pointer that performs additional actions
when an object is accessed
Structure
Participants
• Proxy (ImageProxy)
- maintains a reference that letsthe proxy access the real subject. Proxy may refer to a Subject
if the RealSubject and Subjectinterfaces are the same.
- provides an interface identical to Subject's so that a proxy can by substituted for the real
subject.
- controls access to the real subject and may be responsible for creating and deleting it.
- other responsibilities depend on the kind of proxy:
 remote proxies are responsible for encoding a request and its arguments and
for sending the encoded request to the real subject in a different address space.
 virtual proxies may cache additional information about the real subject so that
they can postpone accessing it. For example, the ImageProxy from the
Motivation caches the real image's extent.
 protection proxies check that the caller has the access permissions required to
perform a request.
• Subject (Graphic)
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 93
- defines the common interface for RealSubject and Proxy so that a Proxy can be used
anywhere a RealSubject is expected.
• RealSubject (Image)
- defines the real object that the proxy represents.
Collaborations
• Proxy forwards requests to RealSubject when appropriate, depending on the kind of proxy.
Consequences
The Proxy pattern introduces a level of indirection when accessing an object. The additional
indirection has many uses, depending on the kind of proxy:
1. A remote proxy can hide the fact that an object resides in a different address space.
2. A virtual proxy can perform optimizations such as creating an object on demand.
3. Both protection proxies and smart references allow additional housekeeping tasks when an
object is accessed.
There's another optimization that the Proxy pattern can hide from the client. It's called copy-
on-write, and it's related to creation on demand. Copying a large and complicated object can
be an expensive operation. If the copy is never modified, then there's no need to incur this
cost. By using a proxy to postpone the copying process, we ensure that we pay the price of
copying the object only if it's modified.
To make copy-on-write work, the subject must be reference counted. Copying the proxy will
do nothing more than increment this reference count. Only when the client requests an
operation that modifies the subject does the proxy actually copy it. In that case the proxy
must also decrement the subject's reference count. When the reference count goes to zero, the
subject gets deleted.
Copy-on-write can reduce the cost of copying heavyweight subjects significantly.
Implementation
The Proxy pattern can exploit the following language features:
1. Overloading the member access operator in C++. C++ supports overloading
operator->, the member access operator. Overloading this operator lets you perform
additional work whenever an object is dereferenced. This can be helpful for
implementing some kinds of proxy; the proxy behaves just like a pointer.
The following example illustrates how to use this technique to implement a virtual
proxy called ImagePtr.
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 94
This approach lets you call Image operations through ImagePtr objects without going to the
trouble of making the operations part of the ImagePtr interface:
Overloading the member access operator isn't a good solution for every kind of proxy.Some
proxies need to know precisely which operation is called, and overloading the member access
operator doesn't work in those cases.
2. Using doesNotUnderstand in Smalltalk. Smalltalk provides a hook that you can use to
support automatic forwarding of requests. Smalltalk calls doesNotUnderstand: aMessage
when a client sends a message to a receiver that has no corresponding method. The Proxy
class can redefine doesNotUnderstand so that the message is forwarded to its subject.
3. Proxy doesn't always have to know the type of real subject. If a Proxy class can deal with
its subject solely through an abstract interface, then there's no need to make a Proxy class for
each RealSubject class; the proxy can deal with all RealSubjectclasses uniformly. But if
V
t
u
C
l
o
u
d
Maharaja Institute of Technology Mysore Department of Information Science & Engineering
Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 95
Proxies are going to instantiate RealSubjects (such as in a virtual proxy), then they have to
know the concrete class.
Known Uses
The virtual proxy example in the Motivation section is from the ET++ text building block
classes.
NEXTSTEP uses proxies (instances of class NXProxy) as local representatives for objects
that may be distributed. A server creates proxies for remote objects when clients request
them. On receiving a message, the proxy encodes it along with its arguments and then
forwards the encoded message to the remote subject. Similarly, the subject encodes any
return results and sends them back to the NXProxy object.
McCullough discusses using proxies in Smalltalk to access remote objects. Pascoe describes
how to provide side-effects on method calls and access control with "Encapsulators."
Related Patterns
Adapter: An adapter provides a different interface to the object it adapts. In contrast, a proxy
provides the same interface as its subject. However, a proxy used for access protection might
refuse to perform an operation that the subject will perform, so its interface may be
effectively a subset of the subject's.
Decorator: Although decorators can have similar implementations as proxies, decorators have
a different purpose. A decorator adds one or more responsibilities to an object, whereas a
proxy controls access to an object.

Software and architecture design pattern

  • 1.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 61 Design Pattern Catalog Structural Patterns 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. Module 2
  • 2.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 62 Meanwhile, an off-the-shelf user interface toolkit might already provide a sophisticated TextView class for displaying and editing text. This diagram illustrates the object adapter case. It shows how BoundingBox requests, declared in class Shape, are converted to GetExtent requests defined in TextView. Since TextShape adapts TextView to the Shape interface, the drawing editor can reuse the otherwise incompatible TextView class. Applicability Use the Adapter pattern when • you want to use an existing class, and its interface does not match the one you need. • you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces. • (object adapter only) you need to use several existing subclasses, but it's unpractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class Structure A class adapter uses multiple inheritance to adapt one interface to another: An object adapter relies on object composition: Participants
  • 3.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 63 • Target (Shape) - defines the domain-specific interface that Client uses. • Client (DrawingEditor) – collaborates with objects conforming to the Target interface. • Adaptec (TextView) - defines an existing interface that needs adapting. • Adapter (TextShape) - adapts the interface of Adaptec to the Target interface. Collaborations • Clients call operations on an Adapter instance. In turn, the adapter calls Adaptec operations that carry out the request. Consequences Class and object adapters have different trade-offs. A class adapter • adapts Adaptee to Target by committing to a concrete Adaptee class. As a consequence, a class adapter won't work when we want to adapt a class and all its subclasses. • lets Adapter override some of Adaptee's behavior, since Adapter is a subclass of Adaptee. • introduces only one object, and no additional pointer indirection is needed to get to the adaptee. An object adapter • Lets a single Adapter work with many Adaptees—that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once. • Makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself. Here are other issues to consider when using the Adapter pattern: 1. How much adapting does Adapter do? Adapters vary in the amount of work they do to adapt Adaptee to the Target interface. There is a spectrum of possible work, from simple interface conversion—for example, changing the names of operations—to supporting an entirely different set of operations. The amount of work Adapter does depends on how similar the Target interface is to Adaptee's. 2. Pluggable adapters. A class is more reusable when you minimize the assumptions other classes must make to use it. By building interface adaptation into a class, you eliminate the assumption that other classes see the same interface. Put another way, interface adaptation lets us incorporate our class into existing systems that might expect different interfaces to the class. Object WorksSmalltalk [Par90] uses the term pluggable adapter to describe classes with built-in interface adaptation. 3. Using two-way adapters to provide transparency. A potential problem with adapters is that they aren't transparent to all clients. An adapted object no longer conforms to the Adaptec interface, so it can't be used as is wherever an Adaptec object can. Two-way adapters can provide such transparency. Specifically, they're useful when two different clients need to view an object differently.
  • 4.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 64 Consider the two-way adapter that integrates Unidraw, a graphical editor framework [VL90], and QOCA, a constraint-solving toolkit [HHMV92]. Both systems have classes that represent variables explicitly: Unidraw has StateVariable, and QOCA has ConstraintVariable. To make Unidraw work with QOCA, ConstraintVariable must be adapted to StateVariable; to let QOCA propagate solutions to Unidraw, StateVariable must be adapted to ConstraintVariable The solution involves a two-way class adapter ConstraintStateVariable, a subclass of both StateVariable and ConstraintVariable that adapts the two interfaces to each other. Multiple inheritance is a viable solution in this case because the interfaces of the adapted classes are substantially different. The two-way class adapter conforms to both of the adapted classes and can work in either system. Implementation Although the implementation of Adapter is usually straightforward, here are some issues to keep in mind: 1. Implementing class adapters in C++.In a C++ implementation of a class adapter, Adapter would inherit publicly from Target and privately from Adaptec. Thus Adapter would be a subtype of Target but not of Adaptec. 2. Pluggable adapters. Let's look at three ways to implement pluggable adapters for the TreeDisplay widget described earlier, which can lay out and display a hierarchical structure automatically. The first step, which is common to all three of the implementations discussed here, is to find a "narrow" interface for Adaptec, that is, the smallest subset of operations that lets us do the adaptation. A narrow interface consisting of only a couple of operations is easier to adapt than an interface with dozens of operations. For TreeDisplay, the adaptee is any hierarchical structure. A minimalist interface might include two operations, one that defines how to present a node in the hierarchical structure graphically, and another that retrieves the node's children. The narrow interface leads to three implementation approaches: (a) Using abstract operations. Define corresponding abstract operations for the narrow Adaptee interface in the TreeDisplay class. Subclasses must implement the abstract operations and adapt the hierarchically structured object. For example, a DirectoryTreeDisplay subclass will implement these operations by accessing the directory structure.
  • 5.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 65 (b) Using delegate objects. In this approach, TreeDisplay forwards requests for accessing the hierarchical structure to a delegate object. TreeDisplay can use a different adaptation strategy by substituting a different delegate. For example, suppose there exists a DirectoryBrowser that uses a TreeDisplay. DirectoryBrowser might make a good delegate for adapting TreeDisplay to the hierarchical directory structure. In dynamically typed languages like Smalltalk or Objective C, this approach only requires an interface for registering the delegate with the adapter. Then TreeDisplay simply forwards the requests to the delegate. NEXTSTEP [Add94] uses this approach heavily to reduce subclassing. (c) Parameterized adapters. The usual way to support pluggable adapters in Smalltalk is to parameterize an adapter with one or more blocks. The block construct supports adaptation without subclassing. A block can adapt a request, and the adapter can store a block for each individual request. In our example, this means TreeDisplay stores one block for converting a node into a GraphicNode and another block for accessing a node's children. Known Uses
  • 6.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 66 The Motivation example comes from ET++Drawing Editor. Related Patterns Bridge has a structure similar to an object adapter, but Bridge has a different intent: It is meant to separate an interface from its implementation so that they can be varied easily and independently. An adapter is meant to change the interface of an existing object. Decorator enhances another object without changing its interface. A decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure adapters. Proxy defines a representative or surrogate for another object and does not change its interface. BRIDGE Intent Decouple an abstraction from its implementation so that the two can vary independently. Also Known As Handle/Body Motivation * When an abstraction can have one of several possible implementations, the usual way to accommodate them is to use inheritance. * An abstract class defines the interface to the abstraction, and concrete subclasses implement it in different ways. * But this approach isn't always flexible enough. Inheritance binds an implementation to the abstraction permanently, which makes it difficult to modify, extends and reuse abstractions and implementations independently. Consider the implementation of a portable Window abstraction in a user interface toolkit. This abstraction should enable us to write applications that work on both the XWindow System and IBM's Presentation Manager (PM), for example. Using inheritance, we could define an abstract class Window and subclasses Xwindow and PMWindow that implement the Window interface for the different platforms. But this approach has two drawbacks: 1. It's inconvenient to extend the Window abstraction to cover different kinds of windows or new platforms. Imagine an IconWindow subclass of Window that specializes the Window abstraction for icons . To support IconWindows for both platforms, we have to implement two new classes, XlconWindow and PMIconWindow. 2. It makes client code platform-dependent.
  • 7.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 67 * The Bridge pattern addresses these problems by putting the Window abstraction and its implementation in separate class hierarchies. * There is one class hierarchy for window interfaces (Window, IconWindow, TransientWindow) and a separate hierarchy for platform-specific window implementations, with Windowlmp as its root. The XWindowImp subclass, for example, provides an implementation basedon the XWindow System. Applicability Use the Bridge pattern when • you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run- time. • both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently. • changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled. • (C++) you want to hide the implementation of an abstraction completely from clients. In C++ the representation of a class is visible in the class interface.
  • 8.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 68 • you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" [RBP+91] to refer to such class hierarchies. • you want to share an implementation among multiple objects(perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class, in which multiple objects can share the same string representation (StringRep). Structure Participants • Abstraction (Window) - defines the abstraction's interface. - maintains a reference to an object of type Implementor. • RefmedAbstraction (IconWindow) – Extends the interface defined by Abstraction. • Implementor (Windowlmp) - defines the interface for implementation classes. This interface doesn't have to correspond exactly to Abstraction's interface; in fact the two interfaces can be quite different. Typically the Implementor interface provides only primitive operations, and Abstraction defines higher-level operations based on these primitives. • Concretelmplementor (XWindowImp, PMWindowImp) - implements the Implementor interface and defines its concrete implementation. Collaborations • Abstraction forwards client requests to its Implementor object. Consequences The Bridge pattern has the following consequences: 1. Decoupling interface and implementation. An implementation is not bound permanently to an interface. The implementation of an abstraction can be configured at run-time. It's even possible for an object to change its implementation at run-time. Decoupling Abstraction and Implementor also eliminates compile-time dependencies on the implementation. Changing an implementation class doesn't require recompiling the Abstraction class and its clients. This property is essential when you must ensure binary compatibility between different versions of a class library. Furthermore, this decoupling encourages layering that can lead to a better
  • 9.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 69 structured system. The high-level part of a system only has to know about Abstraction and Implementor. 2. Improved extensibility. You can extend the Abstraction and Implementor hierarchies independently. 3. Hiding implementation details from clients. You can shield clients from implementation details, like the sharing of implementor objects and the accompanying reference count mechanism (if any). Implementation Consider the following implementation issues when applying the Bridge pattern: 1. Only one Implementor. In situations where there's only one implementation, creating an abstract Implementor class isn't necessary. This is a degenerate case of the Bridge pattern; there's a one-to-one relationship between Abstraction and Implementor. Nevertheless, this separation is still useful when a change in the implementation of a class must not affect its existing clients— that is, they shouldn't have to be recompiled just relinked. 2. Creating the right Implementor object. How, when, and where do you decide which Implementor class to instantiate when there's more than one? If Abstraction knows about all Concretelmplementor classes, then it can instantiate one of them in its constructor; it can decide between them based on parameters passed to its constructor. If, for example, a collection class supports multiple implementations, the decision can be based on the size of the collection. A linked list implementation can be used for small collections and a hash table for larger ones. Another approach is to choose a default implementation initially and change it later according to usage. For example, if the collection grows bigger than a certain threshold, then it switches its implementation to one that's more appropriate for a large number of items 3. Sharing implementors. Coplien illustrates how the Handle/Body idiom in C++ can be used to share implementations among several objects [Cop92]. The Body stores a reference count that the Handle class increments and decrements. The code for assigning handles with shared bodies has the following general form: 4. Using multiple inheritance. You can use multiple inheritance in C++ to combine an interface with its implementation .For example, a class can inherit publicly from Abstraction and privately from a Concretelmplementor. But because this approach relies on static inheritance, it binds an implementation permanently to its
  • 10.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 70 interface. Therefore you can't implement a true Bridge with multiple inheritances—at least not in C++. Known Uses The Window example above comes from ET++ [WGM88]. In ET++, Windowlmp is called "WindowPort" and has subclasses such as XWindowPortand SunWindowPort. The Window object creates its corresponding Implementor object by requesting it from an abstract factory called "WindowSystem." WindowSystem provides an interface for creating platform-specific objects such as fonts, cursors, bitmaps, and so forth. The ET++ Window/WindowPort design extends the Bridge pattern in that the WindowPort also keeps a reference back to the Window. The WindowPort implementor class uses this reference to notify Window about WindowPort-specific events: the arrival of input events, window resizes, etc. Related Patterns An Abstract Factory can create and configure a particular Bridge. The Adapter pattern is geared toward making unrelated classes work together. It is usually applied to systems after they're designed. Bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently. COMPOSITE Intent Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly. Motivation Graphics applications like drawing editors and schematic capture systems let users build complex diagrams out of simple components. The user can group components to form larger components, which in turn can be grouped to form still larger components. A simple implementation could define classes for graphical primitives such as Text and Lines plus other classes that act as containers for these primitives.
  • 11.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 71 The key to the Composite pattern is an abstract class that represents both primitives and their containers. For the graphics system, this class is Graphic. Graphic declares operations like Draw that are specific to graphical objects. It also declares operations that all composite objects share, such as operations for accessing and managing its children. The following diagram shows a typical composite object structure of recursively composed Graphic objects: Applicability Use the Composite pattern when • you want to represent part-whole hierarchies of objects. • you want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly. Structure
  • 12.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 72 A typical Composite object structure might look like this: Participants • Component (Graphic) - declares the interface for objects in the composition. - Implements default behavior for the interface common to all classes, as appropriate. - declares an interface for accessing and managing its child components. - (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate. • Leaf (Rectangle, Line, Text, etc.) - represents leaf objects in the composition. A leaf has no children. - defines behavior for primitive objects in the composition. • Composite (Picture) - defines behavior for components having children.
  • 13.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 73 - stores child components. - implements child-related operations in the Component interface. • Client - manipulates objects in the composition through the Component interface. Collaborations • Clients use the Component class interface to interact with objects in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding Consequences The Composite pattern • defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed, and so on recursively. Wherever client code expects a primitive object, it can also take a composite object. • makes the client simple. Clients can treat composite structures and individual objects uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a leaf or a composite component. This simplifies client code, because it avoids having to write tag-and-case-statement-style functions over the classes that define the composition. • makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don't have to be changed for new Component classes. • can make your design overly general. The disadvantage of making it easy to add new components is that it makes it harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can't rely on the type system to enforce those constraints for you. You'll have to use run-time checks instead. Implementation There are many issues to consider when implementing the Composite pattern: 1. Explicit parent references. Maintaining references from child components to their parent can simplify the traversal and management of a composite structure. The parent reference simplifies moving up the structure and deleting a component. Parent references also help support the Chain of Responsibility pattern. 2. Sharing components. It's often useful to share components, for example, to reduce storage requirements. Butwhen a component can have no more than one parent, sharing components becomes difficult. 3. Maximizing the Component interface. One of the goals of the Composite pattern is to make clients unaware of the specific Leaf or Composite classes they're using. To attain this goal, the Component class should define as many common operations for Composite and Leaf
  • 14.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 74 classes as possible. The Component class usually provides default implementations for these operations, and Leaf and Composite subclasses will override them. However, this goal will sometimes conflict with the principle of class hierarchy design that says a class should only define operations that are meaningful to its subclasses. There are many operations that Component supports that don't seem to make sense for Leaf classes. 4. Declaring the child management operations. Although the Composite class implements the Add and Remove operations for managing children, an important issue in the Composite pattern is which classes declare these operations in the Composite class hierarchy. Should we declare these operations in the Component and make them meaningful for Leaf classes, or should we declare and define them only in Composite and its subclasses? The decision involves a trade-off between safety and transparency: • Defining the child management interface at the root of the class hierarchy gives you transparency, because you can treat all components uniformly. It costs you safety, however, because clients may try to do meaningless things like add and remove objects from leaves. • Defining child management in the Composite class gives you safety, because any attempt to add or remove objects from leaves will be caught at compile-time in a statically typed language like C++. But you lose transparency, because leaves and composites have different interfaces. One approach isto declare an operation Composite* GetComposite ( ) in the Component class. Component provides a default operation that returns a null pointer. The Composite class redefines this operation to return itself through the pointer: GetComposite lets you query a component to see if it's a composite.You can perform Add and Remove safely on the composite it returns.
  • 15.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 75 5. Should Component implement a list of Components? You might be tempted to define the set of children as an instance variable in the Component class where the child access and management operations are declared. But putting the child pointer in the base class incurs a space penalty for every leaf, even though a leaf never has children. This is worthwhile only if there are relatively few children in the structure. 6. Child ordering. Many designs specify an ordering on the children of Composite. In the earlier Graphics example, ordering may reflect front-to-back ordering. If Composites represent parse trees, then compound statements can be instances of a Composite whose children must be ordered to reflect the program. When child ordering is an issue, you must design child access and management interfaces carefully to manage the sequence of children. The Iterator pattern can guide you in this. 7. Caching to improve performance. If you need to traverse or search compositions frequently, the Composite class can cache traversal or search information about its children. The Composite can cache actual results or just information that lets it short-circuit the traversal or search. For example, the Picture class from the Motivation example could cache the bounding box of its children. During drawing or selection, this cached bounding box lets the Picture avoid drawing or searching when its children aren't visible in the current window. Changes to a component will require invalidating the caches of its parents. This works best when components know their parents. So if you're using caching, you need to define an interface for telling composites that their caches are invalid. 8. Who should delete components? In languages without garbage collection, it's usually best to make a Composite responsible for deleting its children when it's destroyed. An exception to this rule is when Leaf objects are immutable and thus can be shared. 9. What's the best data structure for storing components? Composites may use a variety of data structures to store their children, including linked lists, trees, arrays, and hash tables. The choice of data structure depends (as always) on efficiency. Known Uses The RTL Smalltalk compiler framework [JML92] uses the Composite pattern extensively.
  • 16.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 76 Related Patterns Often the component-parent link is used for a Chain of Responsibility. Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild. Flyweight lets you share components, but they can no longer refer to their parents. Iterator can be used to traverse composites. Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes. DECORATOR Intent * Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. Also Known As Wrapper Motivation * Sometimes we want to add responsibilities to individual objects, not to an entire class. A graphical user interface toolkit, for example, should let you add properties like borders or behaviors like scrolling to any user interface component. One way to add responsibilities is with inheritance. Inheriting a border from another class puts a border around every subclass instance. This is inflexible, however, because the choice of border is made statically. A client can't control how and when to decorate the component with a border. A more flexible approach is to enclose the component in another object that adds the border. The enclosing object is called a decorator. The decorator conforms to the interface of the component it decorates so that its presence is transparent to the component's clients. The decorator forwards requests to the component and may perform additional actions (such as drawing a border) before or after forwarding. Transparency lets you nest decorators recursively, thereby allowing an unlimited number of added responsibilities For example, suppose we have a TextView object that displays text in a window. TextView has no scroll bars by default, because we might not always need them. When we do, we can use a ScrollDecorator to add them.
  • 17.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 77 Suppose we also want to add a thick black border around the TextView. We can use a BorderDecorator to add this as well. We simply compose the decorators with the TextView to produce the desired result The ScrollDecorator and BorderDecorator classes are subclasses of Decorator, an abstract class for visual components that decorate other visual components. * VisualComponent is the abstract class for visual objects. It defines their drawing and event handling interface. * Decorator subclasses are free to add operations for specific functionality. For example, ScrollDecorator's ScrollTo operation lets other objects scroll the interface if they know there happens to be a ScrollDecorator object in the interface. Applicability Use Decorator • to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects. • for responsibilities that can be withdrawn. • when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination.
  • 18.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 78 Structure Participants • Component (VisualComponent) - defines the interface for objects that can have responsibilities added to them dynamically. • ConcreteComponent (TextView) - defines an object towhich additional responsibilities canbe attached. • Decorator - maintains a reference to a Component object and defines an interface that conforms to Component's interface. • ConcreteDecorator (BorderDecorator, ScrollDecorator) - adds responsibilities to the component. Collaborations • Decorator forwards requests to its Component object. It may optionally perform additional operations before and after forwarding the request. Consequences The Decorator pattern has at least two key benefits and two liabilities: 1. More flexibility than static inheritance. The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance. With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility (e.g., BorderedScrollableTextView, BorderedTextView). This gives rise to many classes and increases the complexity of a system. Furthermore, providing different Decorator classes for a specific Component class lets you mix and match responsibilities
  • 19.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 79 2. Avoids feature-laden classes high up in the hierarchy. Decorator offers a payas-you-go approach to adding responsibilities. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects. Functionality can be composed from simple pieces. As a result, an application needn't pay for features it doesn't use. It's also easy to define new kinds of Decorators independently from the classes of objects they extend, even for unforeseen extensions. Extending a complex class tends to expose details unrelated to the responsibilities you're adding. 3. A decorator and its component aren't identical. A decorator acts as a transparent enclosure. But from an object identity point of view, a decorated component is not identical to the component itself. Hence you shouldn't rely on object identity when you use decorators. 4. Lots of little objects. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug. Implementation Several issues should be considered when applying the Decorator pattern: 1. Interface conformance. A decorator object's interface must conform to the interface of the component it decorates. ConcreteDecorator classes must therefore inherit from a common class (at least in C++). 2. Omitting the abstract Decorator class. There's no need to define an abstract Decorator class when you only need to add one responsibility. That's often the case when you're dealing with an existing class hierarchy rather than designing a new one. In that case, you can merge Decorator's responsibility for forwarding requests to the component into the ConcreteDecorator. 3. Keeping Component classes lightweight. To ensure a conforming interface, components and decorators must descend from a common Component class. It's important to keep this common class lightweight; that is, it should focus on defining an interface, not on storing data. The definition of the data representation should be deferred to subclasses; otherwise the complexity of the Component class might make the decorators too heavyweight to use in quantity. Putting a lot of functionality into Component also increases the probability that concrete subclasses will pay for features they don't need. 4. Changing the skin of an object versus changing its guts. We can think of a decorator as a skin over an object that changes its behavior. An alternative is to change the object's guts. The Strategy pattern is a good example of a pattern for changing the guts. For example, we can support different border styles by having the component defer border- drawing to a separate Border object. The Border object is a Strategy object that encapsulates a border-drawing strategy. By extending the number of strategies from just one to an open- ended list, we achieve the same effect as nesting decorator recursively. In MacApp 3.0 and Bedrock, for example, graphical components (called "views") maintain a list of "adorner" objects that can attach additional adornments like borders to a view
  • 20.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 80 component. If a view has any adorners attached, then it gives them a chance to draw additional embellishments. MacApp and Bedrock must use this approach because the Viewclass is heavyweight. It would be too expensive to use a full-fledged View just to add a border. Since the Decorator pattern only changes a component from the outside, the component doesn't have to know anything about its decorators; that is, the decorators are transparent to the component: With strategies, the component itself knows about possible extensions. So it has to reference and maintain the corresponding strategies: Known Uses Many object-oriented user interface toolkits use decorators to add graphical embellishments to widgets. Examples include Interviews [LVC89, LCI+92], ET++ [WGM88], and the Object WorksSmalltalkclass library [Par90]. More exotic applications of Decorator are the DebuggingGlyph from Interviews and the PassivityWrapper from ParcPlace Smalltalk. Streams are a fundamentalabstractionin most I/O facilities. Astream can provide an interface for converting objects into a sequence of bytes or characters. That lets us transcribe an object to a file or to a string in memory for retrieval later. A straightforward way to do this is to define an abstractStream class with subclasses MemoryStream and FileStream. But suppose we also want to be able to do the following: • Compress the stream data using different compression algorithms (runlength encoding, Lempel-Ziv, etc.). • Reduce the stream data to 7-bit ASCII characters so that it can be transmitted over an ASCII communication channel. The Decorator pattern gives us an elegant way to add these responsibilities to streams. The diagram below shows one solution to the problem:
  • 21.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 81 For example, the CompressingStream subclass compresses the data, and the ASCII7Stream converts the data into 7-bit ASCII. Now, to create a FileStream that compresses its data and converts the compressed binary data to 7-bitASCII, we decorate a FileStream with a CompressingStream and an ASCII7Stream: Related Patterns Adapter: A decorator is different from an adapter in that a decorator only changes an object's responsibilities, not its interface; an adapter will give an object a completely new interface. Composite A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilities—it isn't intended for object aggregation. Strategy: A decorator lets you change the skin of an object; a strategy lets you change the guts. These are two alternative ways of changing an object.
  • 22.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 82 FACADE Intent Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. Motivation Structuring a system into subsystems helps reduce complexity. A common design goal is to minimize the communication and dependencies between subsystems. One way to achieve this go al is to introduce a facade object that provides a single, simplified interface to the more general facilities of a subsystem. This subsystem contains classes such as Scanner, Parser, ProgramNode, BytecodeStream, and Program NodeBuilder that implement the compiler. To provide a higher-level interface that can shield clients from these classes, the compiler subsystem also includes a Compiler class. This class defines a unified interface to the compiler's functionality. The Compiler class acts as a facade: It offers clients a single, simple interface to the compiler subsystem
  • 23.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 83 Applicability Use the Façade pattern when • you want to provide a simple interface to a complex subsystem • there are many dependencies between clients and the implementation classes of an abstraction. • you want to layer your subsystems. Structure
  • 24.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 84 Participants • Facade (Compiler) - knows which subsystem classes are responsible for a request. - delegates client requests to appropriate subsystem objects. • Subsystem classes (Scanner, Parser, ProgramNode, etc.) - implement subsystem functionality. - handle work assigned by the Facade object. - have no knowledge of the facade; that is, they keep no references to it. Collaborations • Clients communicate with the subsystem by sending requests to Facade, which forwards them to the appropriate subsystem object(s). Although the subsystem objects perform the actual work, the facade may have to do work of its own to translate its interface to subsystem interfaces. • Clients that use the facade don't have to access its subsystem objects directly. Consequences The Facade pattern offers the following benefits: 1. It shields clients from subsystem components, thereby reducing the number of objects that clients deal with and making the subsystem easier to use. 2. It promotes weak coupling between the subsystem and its clients. Often the components in a subsystem are strongly coupled. Weak coupling lets you vary the components of the subsystem without affecting its clients. Facades help layer a system and the dependencies between objects. They can eliminate complex or circular dependencies. This can be an important consequence when the client and the subsystem are implemented independently. 3. It doesn't prevent applications from using subsystem classes if they need to. Thus you can choose between ease of use and generality. Implementation Consider the following issues when implementing a facade: 1. Reducing client-subsystem coupling. The coupling between clients and the subsystem can be reduced even further by making Facade an abstract class with concrete subclasses for different implementations of a subsystem. Then clients can communicate with the subsystem through the interface of the abstract Facade class. This abstract coupling keeps clients from knowing which implementation of a subsystem is used. An alternative to subclassing is to configure a Facade object with different subsystem objects. To customize the facade, simply replace one or more of its subsystem objects.
  • 25.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 85 2. Public versus private subsystem classes. A subsystem is analogous to a class in that both have interfaces, and both encapsulate something—a class encapsulates state and operations, while a subsystem encapsulates classes. And just as it's useful to think of the public and private interface of a class, we can think of the public and private interface of a subsystem. The public interface to a subsystem consists of classes that all clients can access; the private interface is just for subsystem extenders. For example, the classes Parser and Scanner in the compiler subsystem are part of the public interface Known Uses The compiler example in the Sample Code section was inspired by the Object WorksSmalltalk compiler system In the ET++ application framework [WGM88], an application can have built-in browsing tools for inspecting its objects at run-time. These browsing tools are implemented in a separate subsystem that includes a Facade class called "ProgrammingEnvironment." This facade defines operations such as InspectObject and InspectClass for accessing the browsers. The Choices operating system [CIRM93] uses facades to compose many frameworks into one. The key abstractions in Choices are processes, storage, and address spaces. For each of these abstractions there is a corresponding subsystem, implemented as a framework, that supports porting Choices to a variety of different hardware platforms. Two of these subsystems have a "representative" (i.e., facade). These representatives are FileSystemlnterface (storage) and Domain (address spaces). For example, the virtual memory framework has Domain as its facade. A Domain represents an address space. It provides a mapping between virtual addresses and offsets into memory objects, files, or backing store. The main operations on Domain support adding a memory object at a particular address, removing a memory object, and handling a page fault.
  • 26.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 86 As the preceding diagram shows, the virtual memory subsystem uses the following components internally:  MemoryObject represents a data store.  MemoryObjectCache caches the data of MemoryObjects in physical memory. MemoryObjectCache is actually a Strategy that localizes the caching policy.  AddressTranslation encapsulates the address translation hardware. Related Patterns Abstract Factory can be used with Facade to provide an interface for creating subsystem objects in a subsystem-independent way. Abstract Factory can also be used as an alternative to Facade to hide platform-specific classes. Mediator is similar to Facade in that it abstracts functionality of existing classes. However, Mediator's purpose is to abstract arbitrary communication between colleague objects, often centralizing functionality that doesn't belong in any one of them. A mediator's colleagues are aware of and communicate with the mediator instead of communicating with each other directly. In contrast, a facade merely abstracts the interface to subsystem objects to make them easier to use; it doesn't define new functionality, and subsystem classes don't know about it. Usually only one Facade object is required. Thus Facade objects are often Singletons. FLYWEIGHT Intent Use sharing to support large numbers of fine-grained objects efficiently. Motivation Some applications could benefit from using objects throughout their design, but a naive implementation would be prohibitively expensive. * Most document editor implementations have text formatting and editing facilities that are modularized to some extent. Object-oriented document editors typically use objects to represent embedded elements like tables and figures.
  • 27.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 87 The drawback of such a design is its cost. Even moderate-sized documents may require hundreds of thousands of character objects, which will consume lots of memory and may incur unacceptable run-time overhead. A flyweight is a shared object that can be used in multiple contexts simultaneously. The flyweight acts as an independent object in each context—it's indistinguishable from an instance of the object that's not shared. Flyweights cannot make assumptions about the context in which they operate. The key concept here is the distinction between intrinsic and extrinsic state. Intrinsic state is stored in the flyweight; it consists of information that's independent of the flyweight's context, thereby making it sharable. Extrinsic state depends on and varies with the flyweight‗s context and therefore can't be shared. Client objects are responsible for passing extrinsic state to the flyweight when it needs it.
  • 28.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 88 A flyweight representing the letter "a" only stores the corresponding character code; it doesn't need to store its location or font. Clients supply the context dependent information that the flyweight needs to draw itself. For example, a Row glyph knows where its children should draw themselves so that they are tiled horizontally. Applicability The Flyweight pattern's effectiveness depends heavily on how and where it's used. • An application uses a large number of objects. • Storage costs are high because of the rapid quantity of objects. • Most object state can be made extrinsic • The application doesn't depend on object identity Structure
  • 29.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 89 Participants Flyweight (Glyph) - declares an interface through which flyweights can receive and act on extrinsic state. • ConcreteFlyweight (Character) - implements the Flyweight interface and adds storage for intrinsic state, if any. A ConcreteFlyweight object must be sharable. Any state it stores must be intrinsic; that is, it must be independent of the ConcreteFlyweight object's context. • UnsharedConcreteFlyweight (Row, Column) - not all Flyweight subclasses need to be shared. The Flyweight interface enables sharing; it doesn't enforce it. It's common for UnsharedConcreteFlyweight objects to have ConcreteFlyweight objects as children at some level in the flyweight object structure (as the Row and Column classes have). • FlyweightFactory - creates and manages flyweight objects. - ensures that flyweights are shared properly. When a client requests a flyweight, the FlyweightFactory object supplies an existing instance or creates one, if none exists. • Client - maintains a reference to flyweight(s). - computes or stores the extrinsic state of flyweight(s). Collaborations • State that a flyweight needs to function must be characterized as either intrinsic or extrinsic. Intrinsic state is stored in the ConcreteFlyweight object; extrinsic state is stored or computed by Client objects. Clients pass this state to the flyweight when they invoke its operations. • Clients should not instantiate ConcreteFlyweights directly. Clients must obtain ConcreteFlyweight objects exclusively from the FlyweightFactory object to ensure they are shared properly. Consequences Flyweights may introduce run-time costs associated with transferring, finding, and/or computing extrinsic state, especially if it was formerly stored as intrinsic state. However, such costs are offset by space savings, which increase as more flyweights are shared. Storage savings are a function of several factors: • the reduction in the total number of instances that comes from sharing • the amount of intrinsic state per object • whether extrinsic state is computed or stored
  • 30.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 90 Implementation Consider the following issues when implementing the Flyweight pattern: 1. Removing extrinsic state. The pattern's applicability is determined largely by how easy it is to identify extrinsic state and remove it from shared objects. Removing extrinsic state won't help reduce storage costs if there are as many different kinds of extrinsic state as there are objects before sharing. Ideally, extrinsic state can be computed from a separate object structure, one with far smaller storage requirements. In our document editor, for example, we can store a map of typographic information in a separate structure rather than store the font and type style with each character object. The map keeps track of runs of characters with the same typographic attributes. When a character draws itself, it receives its typographic attributes as a side-effect of the draw traversal. Because documents normally use just a few different fonts and styles, storing this information externally to each character object is far more efficient than storing it internally. 2. Managing shared objects. Because objects are shared, clients shouldn't instantiate them directly. FlyweightFactory lets clients locate a particular flyweight. FlyweightFactory objects often use an associative store to let clients look up flyweights of interest. For example, the flyweight factory in the document editor example can keep a table of flyweights indexed by character codes. The manager returns the proper flyweight given its code, creating the flyweight if it does not already exist. Known Uses ET++ [WGM88] uses flyweights to support look-and-feel independence. The look-and-feel standard affects the layout of user interface elements (e.g., scroll bars, buttons, menus— known collectively as "widgets") and their decorations (e.g., shadows, beveling). A widget delegates all its layout and drawing behavior to a separate Layout object. Changing the Layout object changes the look and feel, even at run-time. The Layout objects are created and managed by Look objects. The Look class is an Abstract Factory that retrieves a specific Layout object with operations like GetButtonLayout, GetMenuBarLayout, and so forth. For each look-and-feel standard there is a corresponding Looksubclass (e.g., MotifLook, OpenLook)that supplies the appropriate Layoutobjects. By the way, Layout objects are essentially strategies (see Strategy). They are an example of a strategy object implemented as a flyweight. Related Patterns The Flyweight pattern is often combined with the Composite pattern to implement a logically hierarchical structure in terms of a directed-acyclic graph with shared leaf nodes. It's often best to implement State and Strategy objects as flyweights.
  • 31.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 91 PROXY Intent Provide a placeholder for another object to control access to it. Also Known As Surrogate Motivation Consider a document editor that can embed graphical objects in a document. Some graphical objects, like large raster images, can be expensive to create. But opening a document should be fast, so we should avoid creating all the expensive objects at once when the document is opened. This isn't necessary anyway, because not all of these objects will be visible in the document at the same time. The image proxy creates the real image only when the document editor asks it to display itself by invoking its Draw operation. The proxy forwards subsequent requests directly to the image. It must therefore keep a reference to the image after creating it Applicability
  • 32.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 92 1. A remote proxy provides a local representative for an object in a different address space 2. A virtual proxy creates expensive objects on demand. 3. A protection proxy controls access to the original object 4. A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed Structure Participants • Proxy (ImageProxy) - maintains a reference that letsthe proxy access the real subject. Proxy may refer to a Subject if the RealSubject and Subjectinterfaces are the same. - provides an interface identical to Subject's so that a proxy can by substituted for the real subject. - controls access to the real subject and may be responsible for creating and deleting it. - other responsibilities depend on the kind of proxy:  remote proxies are responsible for encoding a request and its arguments and for sending the encoded request to the real subject in a different address space.  virtual proxies may cache additional information about the real subject so that they can postpone accessing it. For example, the ImageProxy from the Motivation caches the real image's extent.  protection proxies check that the caller has the access permissions required to perform a request. • Subject (Graphic)
  • 33.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 93 - defines the common interface for RealSubject and Proxy so that a Proxy can be used anywhere a RealSubject is expected. • RealSubject (Image) - defines the real object that the proxy represents. Collaborations • Proxy forwards requests to RealSubject when appropriate, depending on the kind of proxy. Consequences The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy: 1. A remote proxy can hide the fact that an object resides in a different address space. 2. A virtual proxy can perform optimizations such as creating an object on demand. 3. Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed. There's another optimization that the Proxy pattern can hide from the client. It's called copy- on-write, and it's related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there's no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it's modified. To make copy-on-write work, the subject must be reference counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject's reference count. When the reference count goes to zero, the subject gets deleted. Copy-on-write can reduce the cost of copying heavyweight subjects significantly. Implementation The Proxy pattern can exploit the following language features: 1. Overloading the member access operator in C++. C++ supports overloading operator->, the member access operator. Overloading this operator lets you perform additional work whenever an object is dereferenced. This can be helpful for implementing some kinds of proxy; the proxy behaves just like a pointer. The following example illustrates how to use this technique to implement a virtual proxy called ImagePtr.
  • 34.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 94 This approach lets you call Image operations through ImagePtr objects without going to the trouble of making the operations part of the ImagePtr interface: Overloading the member access operator isn't a good solution for every kind of proxy.Some proxies need to know precisely which operation is called, and overloading the member access operator doesn't work in those cases. 2. Using doesNotUnderstand in Smalltalk. Smalltalk provides a hook that you can use to support automatic forwarding of requests. Smalltalk calls doesNotUnderstand: aMessage when a client sends a message to a receiver that has no corresponding method. The Proxy class can redefine doesNotUnderstand so that the message is forwarded to its subject. 3. Proxy doesn't always have to know the type of real subject. If a Proxy class can deal with its subject solely through an abstract interface, then there's no need to make a Proxy class for each RealSubject class; the proxy can deal with all RealSubjectclasses uniformly. But if
  • 35.
    V t u C l o u d Maharaja Institute ofTechnology Mysore Department of Information Science & Engineering Software Architecture & Design Pattern (15IS72), 3.Design Pattern Catalog Page | 95 Proxies are going to instantiate RealSubjects (such as in a virtual proxy), then they have to know the concrete class. Known Uses The virtual proxy example in the Motivation section is from the ET++ text building block classes. NEXTSTEP uses proxies (instances of class NXProxy) as local representatives for objects that may be distributed. A server creates proxies for remote objects when clients request them. On receiving a message, the proxy encodes it along with its arguments and then forwards the encoded message to the remote subject. Similarly, the subject encodes any return results and sends them back to the NXProxy object. McCullough discusses using proxies in Smalltalk to access remote objects. Pascoe describes how to provide side-effects on method calls and access control with "Encapsulators." Related Patterns Adapter: An adapter provides a different interface to the object it adapts. In contrast, a proxy provides the same interface as its subject. However, a proxy used for access protection might refuse to perform an operation that the subject will perform, so its interface may be effectively a subset of the subject's. Decorator: Although decorators can have similar implementations as proxies, decorators have a different purpose. A decorator adds one or more responsibilities to an object, whereas a proxy controls access to an object.