SA&DP Notes
SA&DP Notes
ON
Mr. P. SURESH
ASST.PROFESSOR
UNIT I
Introduction: What is Software Architecture? An Engineering Discipline for Software, The
Status of Software Architecture.
Architectural Styles: Architectural Styles, Pipes and Filters, Data Abstraction and Object-
Oriented Organization, Event-Based, Implicit Invocation, Layered Systems, Repositories,
Interpreters, Process Control, Other Familiar Architectures, Heterogeneous Architectures.
Shared Information Systems: Shared Information Systems, Database Integration, Integration in
Software Development Environments, Architectural Structures for Shared Information Systems.
UNIT II
Introduction: What Is a Design Pattern? Design Patterns in Smalltalk MVC, Describing Design
Patterns, The Catalog of Design Patterns, Organizing the Catalog, How Design Patterns Solve
Design Problems, How to Select a Design Pattern, How to Use a Design Pattern.
Creational Patterns: Abstract Factory, Builder, Factory Method, Prototype, Singleton,
Discussion of Creational Patterns.
UNIT III
Structural Pattern Part-I: Adapter, Bridge, Composite.
Structural Pattern Part-II: Decorator, Facade, Flyweight, Proxy.
UNIT IV
Behavioral Patterns Part-I: Chain of Responsibility, Command, Interpreter, Iterator, Mediator,
Memento, Observer.
UNIT V
Behavioral Patterns Part-II: State, Strategy, Template Method, Visitor, Discussion of
Behavioral Patterns. A Case Study (Designing a Document Editor): Design Problems,
Document Structure, Formatting, Embellishing the User Interface, Supporting Multiple Look-
Text Books:
1. Design Patterns By Erich Gamma, Pearson Education
2. Software Architecture: Perspective on an Emerging Discipline By Mary Shaw, David
Garlan, PHI.
Reference Books:
1. Software Architecture in Practice by Len Bass, Paul Clements, Rick Kazman, Third
Edition, Pearson Education.
2. Head First Design Patterns By Eric Freeman-Oreilly-spd.
3. Design Patterns Explained By Alan Shalloway, Pearson Education.
4. Pattern Oriented Software Architecture, F.Buschmann & others, John Wiley & Sons
5. Patterns in JAVA Vol-I By Mark Grand, Wiley DreamTech.
6. Patterns in JAVA Vol-II By Mark Grand, Wiley DreamTech.
7. JAVA Enterprise Design Patterns Vol-III By Mark Grand, Wiley DreamTech
Example 1: Best known examples of pipe-and-filter architecture are programs written in UNIX-
SHELL. Unix supports this style by providing a notation for connecting components [Unix
process] and by providing run-time mechanisms for implementing pipes.
Example 2: Traditionally compilers have been viewed as pipeline systems. Stages in the pipeline
include lexical analysis parsing, semantic analysis and code generation other examples of this
type are.
Signal processing domains
Parallel processing
Functional processing
Distributed systems.
Advantages:
They allow the designer to understand the overall input/output behavior of a system as a
simple composition of the behavior of the individual filters.
Examples:
Layered communication protocol
Operating systems
Fig: Interpreter
Feedforward control:
It anticipates future effects on the controlled variable by measuring other process
variables and adjusts the process based on these variables. The important components of a feed
forward controller are essentially the same as for a feedback controller except that the sensor(s)
obtain values of input or intermediate variables.
The system structure is easier to understand if we first isolate the database updates. Figure 7
focuses narrowly on the database and its transactions. This is an instance of a fairly common
architecture, a repository, in which shared persistent data is manipulated by independent
functions each of which has essentially no permanent state. It is the core of a database system.
A more appropriate view of this structure would re-direct attention from the sequence of
passes to the central shared representation.
Repository:
Batch sequential tools and compilers--even when organized as repositories do not retain
information from one use to another. As a result, a body of knowledge about the program
is not accumulated.
The repository of the compiler provided a focus for this data collection.
Some of the ways that tools could interact with a shared repository.
Tight coupling: Share detailed knowledge of the common, but proprietary,
representation among the tools of a single vendor
Open representation: Publish the representation so that tools can be developed by many
sources. Often these tools can manipulate the data, but they are in a poor position to
change the representation for their own needs.
Hierarchical Layers:
Current work on integration emphasizes interoperability of tools, especially in distributed
systems.
It resembles in some ways the layered architecture with mediators for databases, but it is
more elaborate because it attempts to integrate communications and user interfaces as
well as representation.
It also embeds knowledge of software development processes, such as the order in which
tools must be used and what situations call for certain responses.
This model provides for integration of data, it provides communication and user interface
services directly.
The integration system defined a set of "events" (e.g., "module foo.c recompiled") and
provides support for tools to announce or to receive notice of the occurrence of events.
This example reflects a design that decouples views from models. But the design is
applicable to a more general problem: decoupling objects so that changes to one can affect
any number of others without requiring the changed object to know details of the others. This
more general design is described by the Observer design pattern.
Another feature of MVC is that views can be nested. For example, a control panel of buttons
might be implemented as a complex view containing nested button views. MVC supports
nested views with the CompositeView class, a subclass of View.
But the design is applicable to a more general problem, which occurs whenever we want to
group objects and treat thegroup like an individual object. This more general design is
described by the Composite design pattern.
MVC also lets you change the way a view responds to user input without changing its visual
presentation. You might want to change the way it responds to the keyboard, for example, or
have it use a pop-up menu instead of command keys. MVC encapsulates the response
mechanism in a Controller object.
MVC uses other design patterns, such as Factory Method to specify the default controller
class for a view and Decorator to add scrolling to a view. But the main relationships in MVC
are given by the Observer, Composite, and Strategy design patterns.
Describing the design patterns in graphical notations, simply capture the end product of
the design process as relationships between classes and objects.
We describe design patterns using a consistent format. Each pattern is divided into
sections according to the following template. The template lends a uniform structure to the
information, making design patterns easier to learn, compare, and use.
Pattern Name and Classification
The pattern's name conveys the essence of the pattern succinctly. A good name is vital,
because it will become part of your design vocabulary.
Intent
This describes, what does the design pattern do? What is its rationale and intent? What
particular design issue or problem does it address?
Also Known As
Other well-known names for the pattern, if any.
Motivation
A scenario that illustrates a design problem and how the class and object structures in the
pattern solve the problem. The scenario will help you understand the more abstract
description of the pattern that follows.
Applicability
What are the situations in which the design pattern can be applied? What are examples of
poor designs that the pattern can address? How can you recognize these situations?
Structure
A graphical representation of the classes in the pattern using a notation based on the
Object Modeling Technique (OMT). We also use interaction diagrams to illustrate
sequences of requests and collaborations between objects.
Participants
The classes and/or objects participating in the design pattern and their responsibilities.
Collaborations
How the participants collaborate to carry out their responsibilities.
Object patterns deal with object relationships, which can be changed at run-time
and are more dynamic.
So the only patterns labeled "class patterns" are those that focus on class relationships.
Note that most patterns are in the Object scope.
Creational class patterns defer some part of object creation to subclasses, while
Creational object patterns defer it to another object.
The Structural class patterns use inheritance to compose classes, while the
Structural object patterns describe ways to assemble objects.
Yet another way to organize design patterns is according to how they reference each
other in their "Related Patterns" sections. Clearly there are many ways to organize design
patterns. Having multiple ways of thinking about patterns will deepen your insight
into what they do, how they compare, and when to apply them.
2.9 AbstractFactory:
Intent:
Provide an interface for creating families of related or dependent objects without
specifying their concrete classes.
Also Known As: Kit
Motivation:
Consider a user interface toolkit that supports multiple look-and-feel standards,
such as Motif and Presentation Manager. Different look-and-feels define different
appearances and behaviors for user interface "widgets" like scroll bars, windows, and
buttons. To be portable across look-and-feel standards, an application should not hard-code
its widgets for a particular look and feel. Instantiating look-and-feel-specific classes of
widgets throughout the application makes it hard to change the look and feel later.
Applicability:
Use the Abstract Factory pattern when
A system should be independent of how its products are created, composed, and
represented.
A system should be configured with one of multiple families of products.
Participants:
AbstractFactory (WidgetFactory)
o Declares an interface for operations that create abstract product objects.
ConcreteFactory (MotifWidgetFactory, PMWidgetFactory)
o Implements the operations to create concrete product objects.
AbstractProduct (Window, ScrollBar)
o Declares an interface for a type of product object.
ConcreteProduct (MotifWindow,MotifScrollBar)
o Defines a product object to be created by the corresponding concrete
factory.
o Implements the AbstractProduct interface.
Client
o Usesonly interfaces declared by AbstractFactory and AbstractProduct
classes.
Consequences:
The AbstractFactory pattern has the following benefits and liabilities:
1. It isolates concrete classes.
2. It makes exchanging product families easy.
3. It promotes consistency among products.
4. Supporting new kinds of products is difficult.
Implementation:
Here are some useful techniques for implementing the Abstract Factory pattern.
1. Factories as singletons.
2. Creating the products.
3. Defining extensible factories.
Sample Code:
ClassMazeFactory can create components of mazes. It builds rooms, walls, and doors
between rooms. It might be used by a program that reads plans for mazes from a file
and builds the corresponding maze. Or it might be used by a program that builds
mazes randomly. Programs that build mazes take a MazeFactory as an argument so
that the programmer can specify the classes of rooms, walls, and doors to
construct.
classMazeFactory {
public:
MazeFactory();
virtual Maze* MakeMaze() const
{ return new Maze; }
virtual Wall* MakeWall() const
{ return new Wall; }
Known Uses:
InterViewsuses the "Kit" suffix to denote AbstractFactory classes. It defines
WidgetKit and DialogKit abstract factories for generating look-and-feel-specific user
interface objects. InterViews also includes a LayoutKit that generates different
composition objects depending on the layout desired.
ET++uses the Abstract Factory pattern to achieve portability across different window
systems.
Related Patterns:
AbstractFactory classes are often implemented with factory methods
(FactoryMethod), but they can also be implemented using Prototype.
A concrete factory is often a singleton (Singleton).
2.10 Builder:
Intent:
Separate the construction of a complex object from its representation so that the same
construction process can create different representations.
Motivation:
A reader for the RTF document exchange format should be able to convert RTF to many
text formats. The reader might convert RTF documents into plain ASCII text or into a text
widget that can be edited interactively. The problem, however, is that the number of possible
conversions is open-ended. So it should be easy to add a new conversion without modifying
the reader.
A solution is to configure the RTFReader class with a TextConverter object that converts
RTF to another textual representation. As the RTFReader parses the RTFdocument, it uses
the TextConverter to perform the conversion. Whenever the RTFReader recognizes an RTF
The Builder pattern captures all these relationships. Each converter class is called a
builder in the pattern, and the reader is called the director.
Applicability:
Use the Builder pattern when
The algorithm for creating a complex object should be independent of the parts that
make up the object and how they're assembled.
The construction process must allow different representations for theobject that's
constructed.
Participants:
Builder (TextConverter)
o Specifies an abstract interface for creating parts of a Product object.
ConcreteBuilder (ASCIIConverter, TeXConverter, TextWidgetConverter)
o Constructs and assembles parts of the product by implementing the Builder
interface.
o Defines and keeps track of the representation it creates.
o Provides an interface for retrieving the product (e.g., GetASCIIText,
GetTextWidget).
Director (RTFReader)
o Constructs an object using the Builder interface.
Product (ASCIIText, TeXText, TextWidget)
o Represents the complex object under construction. ConcreteBuilder builds the
product's internal representation and defines the process by which it's
assembled.
o Includes classes that define the constituent parts, including interfaces for
assembling the parts into the final result.
Collaborations:
The client creates the Director object and configures it with the desired Builder
object.
Consequences:
Here are key consequences of the Builder pattern:
1. It lets you vary a product's internal representation.
2. It isolates code for construction and representation.
3. It gives you finer control over the construction process.
Implementation:
Typically there's an abstract Builder class that defines an operation for each component
that a director may ask it to create.
Here are other implementation issues to consider:
1. Assembly and construction interface.
2. Why no abstract class for products?
3. Empty methods as default in Builder.
Sample Code:
We'll define a variant of the CreateMaze member function that takes a builder of class
MazeBuilder as an argument.
classMazeBuilder {
public:
virtual void BuildMaze() { }
virtual void BuildRoom(int room) { }
virtual void BuildDoor(int roomFrom, int roomTo) { }
virtual Maze* GetMaze() { return 0; }
protected:
MazeBuilder();
};
This interface can create three things: (1) the maze, (2) rooms with a particular room
number, and (3) doors between numbered rooms. The GetMaze operation returns the maze to
Known Uses:
The RTF converter application is from ET++. Its text building block uses a builder to
process text stored in the RTF format.
Builder is a common pattern in Smalltalk-80:
The Parser class in the compiler subsystem is a Director that takes a
ProgramNodeBuilder object as an argument.
ClassBuilder is a builder that Classes use to create subclasses for themselves. In
this case a Class is both the Director and the Product.
ByteCodeStream is a builder that creates a compiled method as a byte array.
ByteCodeStream is a nonstandard use of the Builder pattern, because the complex
object it builds is encoded as a byte array, not as a normal Smalltalk object.
Related Patterns:
Abstract Factory is similar to Builder in that it too may construct complex objects. The
primary difference is that the Builder pattern focuses on constructing a complex object step
by step. Abstract Factory's emphasis is on families of product objects (either simple or
complex). Builder returns the product as a final step, but as far as the Abstract Factory
pattern is concerned, the product gets returned immediately.
A Composite is what the builder often builds.
Applicability:
Use the Factory Method pattern when
A class can't expect the class of objects it must create.
A class wants its subclasses to specify the objects it creates.
Classes delegate responsibility to one of several helper subclasses, and you want to
localize the knowledge of which helper subclass is the delegate.
Participants:
Product (Document)
o Defines the interface of objects the factory method creates.
ConcreteProduct(MyDocument)
o Implements the Product interface.
Creator (Application)
o Declares the factory method, which returns an object of type Product.
o Creator may also define a default implementation of the factory method that
returns a default ConcreteProduct object.
o May call the factory method to create a Product object.
ConcreteCreator(MyApplication)
o Overrides the factory method to return an instance of a ConcreteProduct.
Collaborations:
Creator relies on its subclasses to define the factory method so that it returns an instance
of the appropriate ConcreteProduct.
Consequences:
Factory methods eliminate the need to bind application-specific classes into our code.
The code only deals with the Product interface; therefore it can work with any user-defined
ConcreteProductclasses.
A potential disadvantage of factory methods is that clients might have to subclass the
Creator class just to create a particular ConcreteProduct object.
Implementation:
Consider the following issues when applying the FactoryMethodpattern:
1. Two major varieties. (1) the case when the Creator class is an abstract class and does
not provide an implementation for the factory method it declares, and (2) the case
when the Creator is a concrete class and provides a default implementation for the
factory method.
2. Parameterized factory methods. Another variation on the pattern lets the factory
method create multiple kinds of products. The factory method takes a parameter that
identifies the kind of object to create. All objects the factory method creates will
share the Product interface.
3. Language-specific variants and issues. Different languages lend themselves to other
interesting variations and requirements.
4. Using templates to avoid subclassing. Another potential problem with factory
methods is that they might force you to subclass just to create the appropriate Product
objects. Another way to get around this in C++ is to provide a template subclass of
Creator that's parameterized by the Product class.
5. Naming conventions. It's good practice to use naming conventions that make it clear
you're using factory methods.
Sample Code:
The function CreateMaze builds and returns a maze. One problem with this function is
that it hard-codes the classes of maze, rooms, doors, and walls. We'll introduce factory
methods to let subclasses choose these components.
First we'll define factory methods in MazeGame for creating the maze, room, wall, and
door objects:
class MazeGame {
public:
Known Uses:
Factory methods provide toolkits and frameworks. The preceding document example is a
typical use in MacApp and ET++. The manipulator example is from Unidraw.
Another example in Smalltalk-80 is the factory method parser Class defined by Behavior
(a super class of all objects representing classes).This enables a class to use a customized
parser for its source code.
The Orbix ORB system from IONA Technologies uses Factory Method to generate an
appropriate type of proxy when an object requests a reference to a remote object.
Related Patterns:
Abstract Factory is often implemented with factory methods. Factory methods are usually
called within Template Methods. Prototypes don't require subclassing Creator. However,
they often require an Initialize operation on the Product class. Creator uses Initialize to
initialize the object.
Let's assume the framework provides an abstract Graphic class for graphical components,
like notes and staves. It'll provide an abstract Tool class for defining tools like those in the
palette. The framework also predefines aGraphicTool subclass for tools that create instances
of graphical objects and add them to the document.
But GraphicTool presents a problem to the framework designer. The classes for notes and
staves are specific to our application, but the GraphicTool class belongs to the framework.
GraphicTool doesn't know how to create instances of our music classes to add to the score.
We could subclass GraphicTool for each kind of music object, but that would produce lots
of subclasses that differ only in the kind of music object they instantiate.
The solution lies in making GraphicTool create a new Graphic by copying or "cloning"
an instance of a Graphic subclass. We call this instance a prototype. GraphicToolis
parameterized by the prototype it should clone and add to the document. If all Graphic
subclasses support a Clone operation, then the GraphicTool can clone any kind of Graphic.
So in our music editor, each tool for creating a music object is an instance of
GraphicTool that's initialized with a different prototype. Each GraphicTool instance will
produce a music object by cloning its prototype and adding the clone to the score.
Applicability:
Use the Prototype pattern when a system should be independent of how its products are
created, composed, and represented; and
when the classes to instantiate are specified at run-time, for example, by dynamic
loading; or
to avoid building a class hierarchy of factories that parallels the class hierarchy of
products; or
when instances of a class can have one of only a few different combinations of state.
Participants:
Prototype (Graphic)
o Declares an interface for cloning itself.
ConcretePrototype (Staff, WholeNote, HalfNote)
o Implements an operation for cloning itself.
Client (GraphicTool)
o Creates a new object by asking a prototype to clone itself.
Collaborations:
A client asks a prototype to clone itself.
Consequences:
Prototype has many of the same consequences that Abstract Factory and Builder have:
It hides the concrete product classes from the client, thereby reducing the number of
names clients know about. Moreover, these patterns let a client work with application-
specific classes without modification.
Implementation:
Consider the following issues when implementing prototypes:
1. Using a prototype manager. When the number of prototypes in a system isn't
fixed (that is, they can be created and destroyed dynamically), keep a registry of
available prototypes. Clients won't manage prototypes themselves but will store
and retrieve them from the registry. A client will ask the registry for a prototype
before cloning it. We call this registry a prototype manager.
2. Implementing the Clone operation. The hardest part of the Prototype pattern is
implementing the Clone operation correctly.
3. Initializing clones. While some clients are perfectly happy with the clone as is,
others will want to initialize some or all of its internal state to values of their
choosing.
Sample Code:
We'll define a MazePrototypeFactory subclass of the MazeFactory class.
MazePrototypeFactory will be initialized with prototypes of the objects it will create so
that we don't have to subclass it just to change the classes of walls or rooms it creates.
Known Uses:
Perhaps the first example of the Prototype pattern was in Ivan Sutherland's Sketchpad
system. The first widely known application of the pattern in an object-oriented language
was in ThingLab.
Related Patterns:
Prototype and Abstract Factory are competing patterns in some ways. However,
they can also be used together.
An Abstract Factory might store a set of prototypes from which to clone and
return product objects.
Designs that make heavy use of the Composite and Decorator patterns often can
benefit from Prototype as well.
2.13 Singleton:
Intent:
Ensure a class only has one instance, and provide a global point of access toit.
Motivation:
It's important for some classes to have exactly one instance. Examples:
Although there can be many printers in a system, there should be only one
printer spooler.
How do we ensure that a class has only one instance and that the instance is easily
accessible? A global variable makes an object accessible, but it doesn't keep you from
instantiating multiple objects.
A better solution is to make the class itself responsible for keeping track of its sole
instance. The class can ensure that no other instance can be created, and it can provide a
way to access the instance. This is the Singleton pattern.
Applicability:
Use the Singleton pattern when
there must be exactly one instance of a class, and it must be accessible to
clients from a well-known access point.
when the sole instance should be extensible by subclassing, and clients should
be able to use an extended instance without modifying their code.
Structure:
Participants:
Singleton
o Defines an Instance operation that lets clients access its unique instance.
Instance is a class operation.
o May be responsible for creating its own unique instance.
Collaborations:
Clients access a Singleton instance solely through Singleton's Instance operation.
Implementation:
Here are implementation issues to consider when using the Singleton pattern:
1. Ensuring a unique instance. The Singleton pattern makes the sole instance a
normal instance of a class, but that class is written so that only one instance can
ever be created. A common way to do this is to hide the operation that creates the
instance behind a class operation that guarantees only one instance is created.
2. Subclassing the Singleton class. The main issue is not so much defining the
subclass but installing its unique instance so that clients will be able to use it. The
simplest technique is to determine which singleton you want to use in the
Singleton's Instance operation.
Another way to choose the subclass of Singleton is to take the implementation
of Instance out of the parent class and put it in the subclass.
A more flexible approach uses a registry of singletons. Instead of having
Instance define the set of possible Singleton classes, the Singleton classes can
register their singleton instance by name in a well-known registry. This approach
frees Instance from knowing all possible Singleton classes or instances.
Known Uses:
An example of the Singleton pattern in Smalltalk-80is the set of changes to the code,
which is ChangeSet current. A more subtle example is the relationship between classes
and their meta classes.
The InterViews user interface toolkit uses the Singleton pattern to access the unique
instance of its Session and WidgetKit classes, among others.
Related Patterns:
Many patterns can be implemented using the Singleton pattern: AbstractFactory,
Builder, and Prototype.
All three involve creating a new "factory object" whose responsibility is to create
product objects.
Abstract Factory has the factory object producing objects of several classes.
Builder has the factory object building a complex product incrementally using a
correspondingly complex protocol.
Prototype has the factory object building a product by copying a prototype object.
In this case, the factory object and the prototype are the same object, because the
prototype is responsible for returning the product.
Consider the drawing editor framework described in the Prototype pattern. There are
several ways to parameterize a GraphicTool by the class of product:
By applying the Factory Method pattern, a subclass of GraphicTool will be created
for each subclass of Graphic in the palette. GraphicTool will have a NewGraphic
operation that each GraphicTool subclass will redefine.
By applying the Abstract Factory pattern, there will be a class hierarchy of
GraphicsFactories, one for each Graphic subclass. Each factory creates just one
product in this case: CircleFactory will create Circles, LineFactory will create
Lines, and so on. A GraphicTool will be parameterized with a factory for creating
the appropriate kind of Graphics.
By applying the Prototype pattern, each subclass of Graphics will implement the
Clone operation, and a GraphicTool will be parameterized with a prototype of the
Graphic it creates.
P. Suresh, Asst. Prof., Dept. of CSE, CREC Page 73
Which pattern is best depends on many factors.
In our drawing editor framework, the Factory Method pattern is easiest to use at
first.
Abstract Factory doesn't offer much of an improvement, because it requires an
equally large GraphicsFactory class hierarchy.
Overall, the Prototype pattern is probably the best for the drawing editor
framework, because it only requires implementing a Clone operation on each
Graphics class. That reduces the number of classes, and Clone can be used for
purposes other than pure instantiation.
Factory Method makes a design more customizable and only a little more
complicated.
Other design patterns require new classes, whereas Factory Method only requires
a new operation.
Designs that use Abstract Factory, Prototype, or Builder are even more flexible
than those that use Factory Method, but they're also more complex.
Knowing many design patterns gives you more choices when trading off one
design criterion against another.
Introduction:
Structural patterns are concerned with how classes and objects are composed to form
larger structures.
Structural class patterns use inheritance to compose interfaces or implementations.
Example: The class form of the Adapter pattern.
In general, an adapter makes one interface (the adaptee's) conform to another,
thereby providing a uniform abstraction of different interfaces.
A class adapter accomplishes this by inheriting privately from an adaptee class.
The adapter then expresses its interface in terms of the adaptee's.
Rather than composing interfaces or implementations, structural object patterns
describe ways to compose objects to realize new functionality.
The object composition becomes flexible due to the ability to change the composition at
run-time, which is impossible with static class composition.
Example: Composite pattern.
How to build a class hierarchy made up of classes for two kinds of objects:
primitive and composite.
The composite objects let you compose primitive and other composite objects into
arbitrarily complex structures.
3.1Adapter:
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.
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 impractical to
adapt their interface by subclassing every one. An object adapter can adapt the
interface of its parent class.
Object adapter
Participants:
Target (Shape)
defines the domain-specific interface that Client uses.
Client (DrawingEditor)
collaborates with objects conforming to the Target interface.
Adaptee (TextView)
defines an existing interface that needs adapting.
Adapter (TextShape)
Implementation:
Here are some issues to keep in mind while implementing Adapter:
1. Implementing class adapters in C++. Adapter would inherit publicly from Target and
privately from Adaptee.
2. Pluggable adapters.
Participants:
Abstraction (Window)
defines the abstraction's interface.
maintains a reference to an object of type Implementor.
RefinedAbstraction (IconWindow)
Extends the interface defined by Abstraction.
Implementor (WindowImp)
defines the interface for implementation classes. Typically the Implementor
interface provides only primitive operations, and Abstraction defines higher-
level operations based on these primitives.
ConcreteImplementor (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.
Decoupling Abstraction and Implementor also eliminates compile-time
dependencies on the implementation.
Implementation:
Consider the following implementation issues when applying the Bridge pattern:
1. Only one Implementor.
Useful when a change in the implementation of a class must not affect its existing
clients
2. Creating the right Implementor object.
How, when, and where do you decide which Implementor class to instantiate
when there's more than one?
3. Sharing implementors.
4. Using multiple inheritance.
Sample Code:
class Window {
public:
Window(View* contents);
// requests handled by window
virtual void DrawContents();
virtual void Open();
virtual void Close();
virtual void Iconify();
virtual void Deiconify();
// requests forwarded to implementation
virtual void SetOrigin(const Point& at);
virtual void SetExtent(const Point& extent);
virtual void Raise();
virtual void Lower();
3.3 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.
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:
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.
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.
Implementation:
There are many issues to consider when implementing the Composite pattern:
Explicit parent references.
Sharing components.
Maximizing the Component interface.
Declaring the child management operations.
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.
Defining child management in the Composite class gives you safety.
Should Component implement a list of Components?
Child ordering.
Caching to improve performance.
Who should delete components?
What's the best data structure for storing components? The choice of data structure
depends on efficiency.
Sample Code:
class Equipment {
public:
virtual ~Equipment();
Currency CompositeEquipment::NetPrice () {
Iterator* i = CreateIterator();
Currency total = 0;
for (i->First(); !i->IsDone(); i->Next()) {
total += i->CurrentItem()->NetPrice();
}
delete i;
return total;
}
Known Uses:
The original View class of Smalltalk Model/View/Controller was a Composite, and
nearly every user interface toolkit or framework has followed in its steps, including
ET++ and InterViews, Graphics, and Glyphs.
The RTL Smalltalk compiler framework uses the Composite pattern extensively.
Another example of this pattern occurs in the financial domain, where a portfolio
aggregates individual assets.
The Command pattern describes how Command objects can be composed and
sequenced with a MacroCommand Composite class.
Related Patterns:
Often the component-parent link is used for a Chain of Responsibility.
Decorator is often used with Composite.
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.
The following object diagram shows how to compose a TextView object with
BorderDecorator and ScrollDecorator objects to produce a bordered, scrollable text view:
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. Or a class definition may be hidden or otherwise
unavailable for subclassing.
Participants:
Component (VisualComponent)
defines the interface for objects that can have responsibilities added to them
dynamically.
ConcreteComponent (TextView)
defines an object to which additional responsibilities can be 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.
2. Avoids feature-laden classes high up in the hierarchy.
Sample Code:
class VisualComponent {
public:
VisualComponent();
virtual void Draw();
virtual void Resize();
// ...
};
Void BorderDecorator::Draw () {
Decorator::Draw();
DrawBorder(_width);
}
Known Uses:
Many object-oriented user interface toolkits use decorators
Ex. InterViews, ET++, ObjectWorks\Smalltalk class library
3.5 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 goal is to introduce a facade object that provides a single,
simplified interface to the more general facilities of a subsystem.
Applicability:
Use the Facade 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. Use a facade to define an entry point to each
subsystem level.
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.
Collaborations:
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.
3. It doesn't prevent applications from using subsystem classes if they need to. Thus you
can choose between ease of use and generality.
1. Reducing client-subsystem coupling. Clients that use the facade don't have to access
its subsystem objects directly.
2. Public versus private subsystem classes.
Sample Code :
The Scanner class takes a stream of characters and produces a stream of tokens, one
token at a time.
class Scanner {
public:
Scanner(istream&);
virtual ~Scanner();
virtual Token& Scan();
private:
istream& _inputStream;
};
The class Parser uses a ProgramNodeBuilder to construct a parse tree from a Scanner's
tokens.
class Parser {
public:
Parser();
virtual ~Parser();
virtual void Parse(Scanner&, ProgramNodeBuilder&);
};
Known Uses :
ObjectWorks\Smalltalk compiler system
ET++ application framework
The Choices operating system
3.6 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.
Example: 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.
However, they usually stop short of using an object for each character in the document,
even though doing so would promote flexibility at the finest levels in the application.
Characters and embedded elements could then be treated uniformly with respect to how
they are drawn and formatted.
The following fig. shows how a document editor can use objects to represent
characters.
Participants:
Flyweight
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. Its 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).
3.7 Proxy:
Intent:
Provide a surrogate or placeholder for another object to control access to it.
Also Known As: Surrogate
Motivation:
One reason for controlling access to an object is to defer the full cost of its
creation and initialization until we actually need to use it.
These constraints would suggest creating each expensive object on demand.
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.
The document editor accesses embedded images through interface defined by the
abstract Graphic class.
ImageProxy is a class for images that are created on demand. ImageProxy
maintains the file name as a reference to the image on disk.
The file name is passed as an argument to the ImageProxy constructor.
Applicability:
Proxy is applicable whenever there is a need for a more versatile or sophisticated
reference to an object than a simple pointer.
Here are several common situations in which the Proxy pattern is applicable:
1. A remote proxy provides a local representative for an object in a different address space.
NEXTSTEP uses the class NXProxy for this purpose. Coplien calls this kind of proxy an
"Ambassador."
2. A virtual proxy creates expensive objects on demand. The ImageProxy described in the
Motivation is an example of such a proxy.
3. A protection proxy controls access to the original object. Protection proxies are useful
when objects should have different access rights. For example, KernelProxies in the
Choices operating system provide protected access to operating system objects.
4. A smart reference is a replacement for a bare pointer that performs additional actions
when an object is accessed. Typical uses include
counting the number of references to the real object so that it can be freed
automatically when there are no more references (also called smart-pointers).
loading a persistent object into memory when it's first referenced.
checking that the real object is locked before it's accessed to ensure that no other
object can change it.
Participants:
Proxy (ImageProxy)
maintains a reference that lets the proxy access the real subject. Proxy may
refer to a Subject if the RealSubject and Subject interfaces 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.