0% found this document useful (0 votes)
65 views

How Do We Ensure This?

The document discusses forward and backward compatibility, application binary interfaces (ABIs) vs application programming interfaces (APIs), binary compatibility, and design patterns. It provides examples of how to achieve binary compatibility in C/C++ and discusses run-time type identification (RTTI) as a way to determine an object's actual type when only having a base class pointer. It also discusses inheritance vs composition and the fragile base class problem.

Uploaded by

yugalkumar
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

How Do We Ensure This?

The document discusses forward and backward compatibility, application binary interfaces (ABIs) vs application programming interfaces (APIs), binary compatibility, and design patterns. It provides examples of how to achieve binary compatibility in C/C++ and discusses run-time type identification (RTTI) as a way to determine an object's actual type when only having a base class pointer. It also discusses inheritance vs composition and the fragile base class problem.

Uploaded by

yugalkumar
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 174

Forward and Backwards

Compatibility
• What do they mean?
• Suppose you are writing a web browser. Should the
browser be able to handle future versions of HTML?
– How do we ensure this?
• Suppose we are writing a new web browser. Should it be
able to read in old versions of HTML?
– How to ensure?
• Forward compatibility: The ability of an application to
accept future versions of input.
• Backward compatibility: The ability of an application to
accept previous versions of input.
ABI (Application Binary Interface)
vs. API
• Suppose you are designing and implementing
module that fits within an application.
– You design the interfaces carefully.
– In version 2, you change the implementation, but the
interfaces do not change.
• Does the rest of the application need to be modified? Does it
need to be recompiled?
• Can you make your changes such that the application does
not even need to be recompiled? Why does this matter? Isn’t
recompiling simple?
• Can you make your changes such that the application does
not even need to be relinked?
• Is Node v2 backwards binary compatible with
v1?
– struct Node_v1 {
double x;
int i;
int p1, p2, p3; // For extensibility.
};
struct Node_v2 {
double x;
int i;
double p1;
int p3; // For extensibility.
};
• How to achieve binary compatibility in C/C++/Fortran,
etc.?
– // A.hpp
class Aimpl;
class A {
public:
void method1();
private:
Aimpl *impl;
};
– // A.cpp
void A::method1() { impl->method1(); }
– // Aimpl.hpp
class Aimpl { … };
– // What does a client need to include?
#include “A.hpp”
#include “Aimpl.hpp” // Needed?
– When you modify the implementation by changing A.cpp is a
recompile needed? What about Aimpl.hpp, is a recompile
needed?
• Binary compatibility is important in these
situations:
– Large app. Want to ship bug fixes to
customers.
• With no binary compatibility, what happens? With
binary compatibility?
– Designing an OS. When you upgrade the OS,
what happens to apps?
– Libs and dlls. What happens if there is a bug
in the C library on Windows or Linux?
Design Patterns
Introduction
• Designing reusable object-oriented software is hard.
– Find the right objects/classes.
– Find the right factorization.
– Define the interfaces.
– Define the inheritance hierarchies.
• Solves the problem at hand
– But also general enough to address future problems and
requirements.
• Very hard to get right the first time.
– An iterative process.
• Design it, try reuse, redesign/refactor, try reuse again.
• Do not solve every problem starting from first
principles.
– When building a house, each house does not have to
be designed starting from each nail or screw.
– There are well-known “templates” or “patterns” for
building a house that can then be customized, like
kitchen plans, etc.
– “Each pattern describes a problem which occurs over
and over again in our environment, and then
describes the core of the solution to that problem, in
such a way that you can use this solution a million
times over, without ever doing it the same way twice.”
What is a Design Pattern
• Description of communicating objects and
classes that are then customized to solve
a general design problem in a particular
context.
– Pattern name
• Are names important?
– Problem: when to apply the pattern
– Solution: the elements that make up the
design
– Consequences: results and trade-offs
Organizing Design Patterns
• Purpose:
– Creational
• Dealing with object creation: Factory Method
– Structural
• Dealing with composition: Adapter
– Behavioral
• Dealing with behavior: Visitor
• Scope:
– Class
• Applies primarily to classes
– Object
• Applies primarily to objects
Interface vs. Class
• In common OOP usage:
– Interface: What the methods are named, the
parameters they take, return types, and the
semantics.
– Class: The implementation of the interface, the actual
data members, method implementation code, etc.
• In C++, there is greater ability to mix and match
the features of interfaces and classes, so
interface is somewhat implicit.
– Virtual functions and abstract base classes can be
used to make them more explicit.
– A class with just pure virtual functions and no data
members is essentially an interface.
• What is the interface of this class?
– struct A {
void f(int);
};

• Do these two classes have the same


interface?
– struct A {
void f(int);
};
struct B {
void f(int);
};
• Do Impl1 and Impl2 have the same interface?
– struct Interface {
virtual void f1() = 0;
;
struct Impl1 : public Interface {
virtual void f1() { … }
};
struct Impl2 : public Interface {
virtual void f1() { … }
};

• When we use the word interface, we usually


include semantics. But the programming
language only enforces syntactic.
• Program to the interface, not to the
implementation.
Reuse
• Suppose in the first version of your
application, you have a Engine class,
with methods stop() and start().
• Now you also want a Car class. If you just
inherit from from Engine, you can just
automatically get stop() and start().
• Should you? Or should you use
composition?
• Example:
– class Engine {
public:
void stop();
void start();
};
// Automatically get stop() and start().
class Car1 : public Engine {
};
// This way requires more coding.
class Car2 {
public:
void stop() { engine.start(); }
void start() { engine.stop(); }
private:
Engine engine;
// Engine *engine;
};
• Generally, prefer composition to
inheritance.
Delegation
• One aspect of composition is delegation.
• For example, in a GUI, a Window might be
based on a Rectangle class. If we use
composition, then an invocation of the
area() method of a Window object can
be forwarded to the Rectangle object.
– int Window::area() {
return rect->area();
}
Fragile Base Class
• Often, seemingly safe changes to a base
class cause things to break in the derived
classes.
• Example:
• Someone writes a bag class.
– class Bag {
public:
void add(int);
};
• Some wants to keep track of how many
numbers are in the bag.
– class Bag {
public:
void add(int);
};
class CountingBag : public Bag {
public:
void add(int i) {
count++;
Bag::add(i);
}
};
• Someone wants to add a convenience function
to add a range of numbers at once.
– class Bag {
public:
void add(int);
// addAll() calls add().
void addAll(int i, int j) {
… add(i); … }
};
class CountingBag : public Bag {
public:
void add(int i) {
count++;
Bag::add(i);
}
};
Run-Time Type Identification
(RTTI)
• Sometimes you need to know the actual
type of an object, when you have just a
pointer to the base class.
• How do you do inheritance in C?
• Inheritance in C:
– struct A {
int a_member; };
struct B {
struct A A_sub;
int b_member; };
struct C1 {
struct B B_sub;
int c1_member; };
struct C2 {
struct B B_sub;
int c2_member; };
• Upcasting and downcasting:
– struct C1 c1;
C1_ctor(&c1);
A *a = (A *) &c; // Upcast
B *b = a; // Downcast
A *ap = …; // Pointer to A obtained somehow.
C2 *c2 = (C2 *) ap; // Safe?
• Inheritance in C:
– struct A {
int a_member; };
struct B1 {
struct A A_sub;
int b1_member; };
struct B2 {
struct A A_sub;
int b2_member; };
• How do we be safe? Try to make sure of type.
– A *ap = …; // Pointer to A obtained somehow.
if (/* ap is really a B1 */) {
B1 *b1 = (B1 *) ap;
// Do something with b1 that is B1 specific.
} else if (/* ap is really a B2 */) {
B2 *b2 = (B2 *) ap;
// Do something with b2 that is B2 specific.
}
• Use type ID of some kind.
– struct A {
enum { T_B1, T_B2 } id;
int a_member; };
struct B1 {
struct A A_sub;
int b1_member; };
struct B2 {
struct A A_sub;
int b2_member; };
• Check ID before downcast.
– A *a = …; // Pointer to A obtained somehow.
if (a->id == T_B1) {
B1 *b1 = (B1 *) a;
// Do something with b1 that is B1 specific.
} else if (a->id == T_B2) {
B2 *b2 = (B2 *) a;
// Do something with b2 that is B2 specific.
}
• Error prone: where is the ID set?
– struct A {
enum { B1_T, B2_T } id;

};
struct B1 {
struct A A_sub; };
struct B2 {
struct A A_sub;
};
B1 b1; // No constructor
b1.A_sub.id = B1_T;
• If using C++, can do it in the constructor.
– struct A {
enum { B1_T, B2_T } id;
A(enum Id i) : id(i) {}

};
struct B1 {
B1() : A_sub(B1_T) {}
struct A A_sub; };
struct B2 {
B2() : A_sub(B2_T) {}
struct A A_sub;
};
B1 b1;
• What are more idiomatic C++ solutions?
• What does this do?
– struct A { virtual ~A() {} };
struct B1 : public A { … };
struct B2 : public A { … };
B1 b;
A *a = &b;
B2 *bp = dynamic_cast<B2 *>(a);
bp == ??; // What is the value of bp?

• Can use dynamic casting.


• Can also use RTTI:
– #include <typeinfo>
struct A { virtual ~A() {} };
struct B1 : public A { … };
struct B2 : public A { … };
B1 b;
A *a = &b;
if (typeid(*a) == typeid(B1)) {

} else if (typeid(*a) == typeid(B2)) {

} else if (typeid(*a) == typeid(B3)) {

}
• The typeid operator returns a reference
to an object of class type_info.
• The type_info object has a string name
that can sometimes be helpful for
debugging.
– struct A { virtual ~A() {} };
struct B1 : public A { … };
struct B2 : public A { … };
B1 b;
A *a = &b;
cout << typeid(*a).name() << endl;
• Is this efficient?
– A *a = …; // Obtained somehow.
if (typeid(*a) == typeid(B1)) {

} else if (typeid(*a) == typeid(B2)) {

} else if (typeid(*a) == typeid(B3)) {

} … {
} else if (typeid(*a) == typeid(B100)) {

}

• Solution?
• You could push the code into the object:
– // Original version.
if (typeid(*a) == typeid(B1)) {
// Some code to do XYZ.
} else if (typeid(*a) == typeid(B2)) {
// Some code to do ABC.
}
– // Code moved into a virtual function in the
// object.
virtual void B1::doit() {
// Code to do XYZ.
}
virtual void B2::doit() {
// Code to do ABC.
}

a->doit(); // Outside of the object.
• Disadvantage?
– Intrusive, however.
• The problem is to efficiently map from the
type to the code that should be executed
for that type.
– struct Code {
virtual void operator()(A *) const = 0;
};
struct Code_B1 : public Code {
virtual void operator()(A *) const;
};
map<type_info *, Code, Cmp> type_map;
Code &code = type_map.lookup(&typeid(*a));
code(a);
• In order to efficiently store type_info in
a map, what operation do we need?
– The type_info object has before() method.
Class Diagrams
• Diagram the relationships between
classes.
Abstract class or
interace (Italicized)

Class name

Methods

Member variables
(Only if concrete)
Client Client

Participant Non-participant

• Clients that aren’t active participants in the


pattern are shown in gray.
Aggregation Multiplicity
Interface
Name

Inheritance

Instantiation Acquaintance

• Class relationships
• Pseudo-code annotation
Object Diagrams

• Describe relationships between actual


objects.
Reference
name
Reference

Object name
(aSomeclass)
Interaction Diagrams
• Describe how objects interact.
– How do you do this?
• Function F invokes function G, in two different call
sites.
• In the second invocation, G invokes F.
Object name

Not yet
Instantiation
created

Request name
Object
lifetime

Object
active
Example

• class A {
public:
A() : paren(0), a1(new A(this)),
a2(new A(this)) {}
void start() {
a1->foo();
a2->foo();
}
private:
A(A *p)
: paren(p), a1(0), a2(0) {}
void foo() { paren->goo(); }
void goo();
private:
A *a1, *a2, *paren;
};
Most Common Patterns
Abstract Factory
(Object Creational)
• Intent
– Provide an interface for creating families of related
objects without specifying concrete factories.
• Motivation
– Consider an application with a GUI that needs to run
on both Windows and Linux. You might need to
create a Window with a containing Scrollbar. You
want the Windows version to create Windows
interface objects, and the Linux version to create
Linux interface objects.
• Interface has create methods.
– Concrete derived class creates various concrete
classes.
• Example:
– struct MazeFactory {
virtual Maze *MakeMaze() const = 0;
virtual Wall *MakeWall() const = 0;
};
struct MagicMazeFactory : public MazeFactory {
virtual Maze *MakeMaze() const {
return new MagicMaze; }
virtual Wall *MakeWall() const {
return new MagicWall; }
};
struct BombedMazeFactory
: public MazeFactory { … };
Maze *BuildMaze(MazeFactory *) { … }
// Make a magic maze.
MazeFactory *mmf = new MagicMazeFactory;
Maze *m = BuildMaze(mmf);
// Make a bombed maze.
MazeFactory *bmf = new BombedMazeFactory;
Maze *m = BuildMaze(bmf);
Factory Method
(Class Creational)
• Intent
– Define an interface for creating an object, but
let subclasses decide which class to
instantiate.
• Motivation
– At the point at which an object is created, it is
unknown which actual implementation to use.
• Factory method subclasses the thing creating the
objects.
• Can have a factory method without an abstract factory.
• Suppose you have different kinds of String
implementations, optimized for different
cases:
– Short strings
– Strings that don’t change
– UTF-8 strings
– Etc.
• You want to completely isolate these
optimizations. The rest of the application
should not know that there are different
kinds of string types.
• So, can you put this in application code?
– // Dealing with Unicode, so create
Unicode optimized string.
String *str = new UnicodeString;
• Use a virtual constructor approach.
– class String {
public:
enum LengthType { FIXED, DYNAMIC };
enum Encoding { UTF-8, ASCII };
static String *MakeString(int len,
LengthType,
Encoding);
};
class UTFString : public String {… };

String *String::MakeString(…) {
// Decide which version to make…
if (…) {
return new UTFString(…);
} else if (…) {
return new ASCIIString(…);
} …
}
• Optimized implementations can now be
added completely independently, without
affecting the rest of the application at all.
• Application just says:
– String *s = String::MakeString(…);
Adapter
(Class/Object Structural)
• Intent
– Convert interface of a class into one that is
expected.
• Commonly called a wrapper.
• Can use inheritance or composition.
• Within a single class.
• As two separate objects (probably
preferred).
• Example: Adapt a TextView object to a Shape interface.
– struct Shape {
virtual void BoundingBox(Point &bottom_left,
Point &top_right) const;
};
– class TextView {
void GetOrigin(Coord &x, Coord &y) const;
void GetExtent(Coord &width,
Coord&height) const;
}
• Using inheritance
– class TextShape
: public Shape, private TextView {
BoundingBox(Point &bl, Point &tr) const {
GetOrigin(…);
GetExtent(…);

}
}
• Example: Adapt a TextView object to a Shape interface.
– struct Shape {
virtual void BoundingBox(Point &bottom_left,
Point &top_right) const;
};
– class TextView {
void GetOrigin(Coord &x, Coord &y) const;
void GetExtent(Coord &width,
Coord &height) const;
}
• Using composition
– class TextShape : public Shape {
public:
BoundingBox(Point &bl, Point &tr) const {
tv.GetOrigin(…);
tv.GetExtent(…);

}
private: TextView tv;
}
Composite
(Object Structural)
• Applicability
– Part-whole hierarchies
– Compositions of objects and individual objects
treated the same.
• Example
– An expression is:
• A number by itself
• A variable by itself
• An operator
• A composite of things has the same interface as
the contained things.
• Example:
– class Expression { … };
class Operator : public Expression {

private:
Expression *left, *right;
};
class Leaf : public Expression {

};
Decorator
(Object Structural)
• Intent
– Adding additional responsibilities/functionality
to an object dynamically.
– Alternative to subclassing.
– Differs from Adapter in that Adapter changes
the interface, while Decorator only modifies
the features, not the interface.
• Example:
– class VisualComponent {
public:
virtual void Draw() const;
};
class Decorator : public VisualComponent {
public:
Decorator(VisualComponent *);
virtual void Draw() const;
private:
VisualComponent *comp;
};
void Decorator::Draw() {
comp->Draw();
}
class Border : public Decorator { … };
void Border::Draw() {
Decorator::Draw();
// Do stuff to draw border.
}
• Discussion
– Can be dynamic, unlike subclassing.
– Avoids creating all possible combinations of
subclasses. For example, if there are two
possible decorations, D1, and D2, and two
possible elements, E1, and E2, you would
have to have ? different subclasses.
Observer
• Intent
– Define a dependency (subscription) relationship between
objects, so that when the observed object changes state, all
observers are notified and updated automatically.
– It is the View, in the MVC pattern.
• Motivation
– Suppose you have a set of objects which needs to be notified
when object A changes.
• Applicability
– When a change to one object requires changing others, and you
don’t know how many others need to be changed.
– When an object should be able to notify other objects, and you
don’t know the other objects ahead of time.
• Notify() is called by the subject itself when setstate() is called.
• Example:
– class Observer {
public:
virtual void Update();
};
class Subject {
public:
void Notify() {
for (it = list.begin();
it != list.end(); ++it) {
it->Update();
}
};
class MyObserver : public Observer {
void Update() {
subject->getState();

}
};
class MySubject : public Subject {
void SetState(…) {

Notify();
}
}
• Who should call Notify(), the subject itself, or the object changing the state?
• Suppose an observer itself need to set the state in Update.
• Suppose a derived class operation is composed of several base class
operations.
Strategy
(Object Behavioral)
• Intent: Define a family of algorithms, encapsulate each
one, make them interchangeable.
• Motivation: Many algorithms exist for breaking a stream
of text into lines.
– Do not want to put the code in the clients that need linebreaking.
– Want to support multiple algorithms.
– Want to support easily adding them.
• Applicability:
– You need variants of an algorithm.
– Many related classes differ only in their behavior.
– An algorithm uses data that clients shouldn’t know about.
– A class defines many different behaviors, and these show up as
multiple conditionals in the ops. Move branches into strategy
class.
• Strategy and context collaborate to
provide the behavior.
• Consequences:
– Alternative to subclassing.
• You could subclass the Context object.
– Eliminate conditional statements.
• void Composition::Repair() {
switch (line_breaking_strategy) {
case SIMPLE:
BreakWithSimple();
break;
case TEX:
BreakWithTex();
break;

}
• void Composition::Repair() {
compositor->BreakLines():

}
– A choice of implementations. Makes it easy to compare two
different ones.
• Implementation Issues:
– How do the Strategy and Context
communicate? What is passed?
– Use a template. What are the benefits?
• Example:
– class LineBreaker {
public:
virtual vector<string>
break(const vector<string> &) const;
};
class Paragraph {
public:
Paragraph(const LineBreaker *);
void addLine(const string &);
private:
const LineBreaker *const breaker;
};
void Paragraph::addLine(const string &l) {
// Do stuff to add the line.
lines = line_break->break(lines);
}
Template Method
(Class Behavioral)
• Intent
– Define the overall steps of an operation in a super-
class method, but deferring the exact implementation
of the steps to methods in derived classes.
• Motivation
– You have some code that is similar, but not identical
in multiple classes.
• Factor out the similarity into a template method.
• Use derived class methods (or function pointers) to handle
the similar parts.
• Suppose you have an application
framework with App and Doc objects.
Specific applications, such as a drawing
application or a spreadsheet application
will subclass these.
– One thing in common is the need to open a
document. The overall sequence of steps is
identical for all apps, but the specific details of
how each step is carried out varies.
– So, put the overall sequence in the base
class, and let derived classes define exactly
what to do.
• class App {
void OpenDoc(const char *name);
};
class MyApp {
void CanOpenDoc(const char *name);
Doc *DoCreateDoc(const char *name);
void AboutToOpenDoc(Doc *);
};
void App::OpenDoc(const char *name) {
if (!CanOpenDoc(name)) { return; }
Doc *d = DoCreateDoc(name);
if (d) {
AboutToOpenDoc(d);
d->Open();
d->DoRead();
}
}
void MyApp::CanOpenDoc(const char *name) {
// Do stuff here specific to this app, such as maybe
// check the format of the file to make sure it is of
// the right type.
// …
}
void MyApp::DoCreateDoc(const char *name) { … }
void MyApp::AboutToOpenDoc(Doc *) { … }
• Applicability:
– Implement the invariant parts of an algorithm
once.
• Sort, pick some good candidates using a metric,
run a computation with those candidates, then do
an update based on those results, but also
dependent on the metric.
– When common behavior should be factored
and localized to a superclass.
– Control and define subclass extensions.
• Example: A class called View that supports
drawing on the screen.
– Before drawing can begin, the focus must first be set.
Base class does that, then calls derived class.
– void View::Display() {
SetFocus();
DoDisplay();
ResetFocus();
}
void MyView::DoDisplay() {
// App-defined stuff.
}
– So user derives from base class.
• Tip: Use a naming convention to make clear
what should be implemented by derived class.
• Basic idea here is that you want to put common
code in the base class.
• Is there another way to do the same thing?
– class Base {
void op();
};
class Derived: public Base {
virtual void op() {

Base::op();
}
};
– Advantages, disadvantages?
Patterns Catalog
Related Factory Patterns
• Abstract Factory
– An object with factory methods.
• Factory Method
– A method within an object that is subclassed.
• Builder
– An object to which you feed a sequence of things to it,
then get the result in the end.
• Prototype
– Another way of creating objects via a clone() method.
Builder (Object Creational)
• Intent: Separate the construction of a complex object
from its representation so that the same construction
process can create different representations.
• Motivation: Suppose you have an object to read RTF.
You want it to be able to convert to multiple different
representation types, such as ASCII, or HTML.
Solutions?
– // In reader
while (t = get the next token) {
switch (t.type) {
case CHAR: builder->ConvertChar(t.char);
case FONT: builder->ConvertFont(t.font);
case PARA: builder->ConvertPara(t.para);
• Applicability:
– Algorithm for creating a complex object should
be independent of the parts that make up the
object.
– The construction process must allow for
different representations.
• Builder similar to AF.
– Builder focuses on creating a complex object step-by-step.
– AF focus is on families of product objects.
– Builder often returns product as final step. AF often returns
immediately.
– Where is the product stored?
Prototype
(Object Creational)
• Intent
– Specify the kinds of objects to create using a prototypical
instance, and create new objects by copying this protoype.
• Motivation
– Suppose you have a GUI element called a GraphicTool that
will let you create and place a graphic in a music editor. You
want to create and place a number of different ones, like
WholeNote and HalfNote.
– The GraphicTool needs to instantiate the graphic, such as
WholeNote or HalfNote. You could create one GraphicTool
for each graphic.
– Better is to initialize each GraphicTool with an instance of a
Graphic abstract class, that it then clones.
– Other solutions?
• Could use a factory of some kind.
• class Client {
void Op() {
p = prototype->Clone();
}
}
class MyProto1 : public Proto {
virtual MyProto1 *Clone() { … }
};
class MyProto2 : public Proto {
virtual MyProto2 *Clone() { … }
};
• Do we need to use a separate class for whole
notes and half notes?
• Applicability:
– When class to instantiate are specified at run-
time.
– To avoid building a hierarchy of factories that
parallel the products.
– When instances of a class can have only a
few combinations of state.
• Easier than instantiating manually, especially if
many parameters, but few combinations.
• Example
– class MazePrototypeFactory {
public:
MazePrototypeFactory(Maze*, Wall*, Room *);
virtual Maze *MakeMaze() const;
virtual Room *MakeRoom() const;
virtual Wall *MakeWall() const;
private:
Maze *protoMaze;
Room *protoRoom;
Wall *protoWall;
};
Wall *MazePrototypeFactory::MakeWall() const {
return protoWall->clone();
}
MazePrototypeFactory bombedMF(new Maze, new
BombedWall, new BombedRoom);
• Consequences
– Requires implementing clone(), so is intrusive.
– Does not require a whole set of parallel classes, as
using factories might.
• A factory for each type, like bombed wall, etc.
• The concept is like merging the factory with the object that
it creates.
– Supports user-templates. For example, say you
have a graphic that you want to put into a palette.
– Can be very dynamic, and have prototypes with
different values (but same class). (Factories can do
this to, but not quite as elegant.)
• // Five bombs per wall.
MazeProtoFactory mf5(new BombedWall(5));
// Ten bombs per wall.
MazeProtoFactory mf10(new BombedWall(10));
• Implentation:
– If lots of prototypes, and there is a need to
search for them based on attributes, use a
prototype manager/registry.
Discussion of Factory Patterns
• Two ways of parameterizing a system by the classes of
objects it creates:
– Subclass the class that creates the objects. (FactoryMethod)
– Define an object that is responsible for knowing what to create
(AbstractFactory, Builder, Prototype)
• Consider the GraphicTool.
– FactoryMethod would say subclass it, one to create HalfNote,
the other to create WholeNote.
– AbstractFactory would say pass in a factory object to create
HalfNotes or WholeNotes.
– Prototype would say pass in a prototype object that is cloned.
– Note that the line between these is somewhat blurry sometimes.
Traversing Containers
• Iterator
– Essentially an object that functions as a pointer,or
cursor. It has a current element that it points to, and
methods to advance to the next element.
• Visitor
– For data structures that are heterogeneous. Factor
out the traversal code, and as you traverse the
structure, make callbacks to a visitor object that is
carried along the traversal.
Iterator (Object Behavioral)
• Intent
– Provide a way to access the elements of an
aggregate object sequentially without exposing the
underlying implementation.
• Motivation
– How do you traverse a linked list? How did you learn
how to do it?
– A container like a linked list should have a way of
traversing the elements without exposing its structure.
• Suppose you have a variety of containers, such as a list and
binary tree. You want to do something to every thing in the
container using the same code.
• Or suppose you want to traverse it in different ways, like
forwards and backwards, or using different orderings.
– void foo(List *li) {
ListNode *ptr = li->head;
while (ptr != NULL) {
// Do something with it.
ptr = ptr->next;
}
}
– Suppose it was changed to an array? Or a balanced binary tree?
– Suppose this is traverse monsters. You decide that you want to
filter out invisible ones.
– void foo(Container *li) {
Iterator *it = il->getIterator(no_invisible);
while (it->more()) {
// Do something with it.
it->next();
}
}
– Key Idea: Take the responsibility for traversal and
access out of the container itself, and put it into an
iterator object. The iterator object functions as a
pointer, or cursor, or placeholder, that you can then
advance, etc.
• Using a single interface, different classes of iterator objects
can traverse in different directions, or different ways. For
example, you could have an OddIterator to skip all even
elements.
– class Iterator {
void next();
int get();
};
class OddIterator : public Iterator {…};
IntList l;
OddIterator it(l);
it.get();
it.next();
it.get();
– How does the iterator know how to advance to
the next element? Does it require
implementation knowledge about the
container.
• Yes, so should use a pattern.
– What class should be created? Should it be public?
– class SomeList;
Iterator it = sl.createIterator(); // What
is this pattern?
– SomeListIterator it(sl);
– How can this code be rewritten to make it
more flexible/maintainable/adaptable?
• void foo(List *) {
ListIterator lit(l);
for (; !lit.end(); lit.next()) {
// Do something with lit.get().
}
}
• void foo(Iterator *) {
for (; !lit.end(); lit.next()) {
// Do something with lit.get().
}
}
• Known as polymorphic iteration.
• Applicability: when to use?
– To access a container’s contents without
exposing the internal representation.
– Support different ways of traversing the same
container. For example, in-order or pre-order
traversal of a tree. Or backwards or forwards.
Or filtering out certain elements.
– Provide a uniform interface for traversing
different kinds of containers (polymorphic
iteration).
• Implementation issues:
– External iterators vs. internal iterators.
• Where is the code for traversal defined? It could be in the container, or it
could be in the iterator.

class ListNode { // Internal tree iterator.


private: void TreeNode::traverse(Handler *h)
ListNode *next; {
Object *obj; right->traverse(h);
}; h->handle(elem);
class ListIterator { left->traverse(h);
public: }
void next() { // External tree iterator.
cur = cur->next; class TreeIterator {
} public:
Object *get() { void next() {
return obj; if (cur->left != 0) {
} stack.push(cur);
}; cur = cur->left;
while (cur->right != 0) {
// Tree stack.push(cur);
class TreeNode { cur = cur->right;
public: }
private: }
Node *right, *left; }
Element *elem;
};
– How robust is the iterator?
• // Using a list iterator to delete an element.
List l; ListIterator lit = lit.begin();
while (!lit.end()) {
if (lit.get() == 1234) {
lit.delete(); break;
}
lit.next();
}
• // Suppose you have this.
List l; ListIterator lit = lit.begin();
while (!lit.end()) {
if (lit.get() == 1234) {
foo();
}
lit.next();
}
void foo(ListIterator lit) {
// …
lit.delete();
}
– Additional operations?
• Iterator::skip2();
– How to implement in C++? Pointers?
• Iterator *container::begin() { … }
Iterator container::begin() { … }
Visitor
(Object Behavioral)
• Intent
– Represent an operation to be performed on the elements of an
object structure.
• Motivation
– Suppose you have some operation, like Print, that you that want
to do on some tree data structure consisting of a number of
objects of different types.
– You could add a Print operation to each class. But suppose you
also want to do something like convert to HTML. That also
requires a tree traversal.
– Better to have a Print visitor, and a separate HTML visitor, then
use the Visitor pattern to factor out the traversal code.
• This separates the structure of the container from the operations
that you want to perform.
• Applicability: Use when:
– Object structure contains many different types of
objects that need to be handled differently.
– Many distinct and unrelated ops need to be performed
on the elements of a structure. You could put the ops
in the structure as methods in the structure, but this
pollutes, and limits extensibility:
• class TreeNode {
public:
void convertToHtml(…);
void print(…);
void convertToASN1(…);

};
• Suppose you want to add a new operation. What happens to
users of the above class? What if it is library used throughout
your company? Can you achieve binary compatibility?
Visitor
• Example
– class Node {
virtual void accept(Visitor *) const;
void visitChildrenHelper(Visitor *)
const; };
class RedNode : public Node {
virtual void accept(Visitor) const; };
class BlackNode : public Node {…};
void RedNode::accept(Visitor *v) const {
v->visitRedNode(this);
visitChildrenHelper(v);
}
void BlackNode::accept(Visitor *v) const {
v->visitBlackNode(this);
visitChildrenHelper(v);
}
class Visitor {
virtual void visitRedNode(const RedNode *)
= 0;
virtual void
visitBlackNode(const BlackNode *) = 0;
};
• Consequences: Benefits and liabilities are:
– Makes adding new operations easy. Just
define a new Visitor.
– What about adding new concrete element
types? What if we added a new Node type to
XML?
• May require changing a lot of visitors.
– Can visit objects that don’t have same base
class, etc.
• Visitor and Iterator are related.
– To see the difference, consider a Visitor with
one visit method: visitItem().
• Essentially same as internal iterator.
– Or, think about how to use the iterator to visit
objects of different types.
• Iterator *it;
for (Iterator it = list.begin(); !it.end(); it++) {
if ((*it).type() == … ) { … }
}
Related “Handle-Body” (Wrapper)
Patterns
• Adapter
– Adapts interface
• Bridge
– Allow two abstractions to vary independently by layering one on
top of the other.
• Decorator (same interface)
– A wrapper that adds functionality, but keeps the interface.
• Proxy (same interface)
– A wrapper that “stands-in” for the real thing.
• State
– A wrapper around state-specific implementations. Could be
same interface or not.
Bridge (Object Structural)
• Intent
– Decouple an abstraction from its implementation so
that the two can vary independently.
• Motivation
– Usually, when an abstraction can have one of several
implementations, the solution is inheritance.
• But that means the implementation is bound to the
abstraction. You can’t use the same implementation for a
different abstraction. (Because you can’t dynamically change
the base class. MI does allow you to statically support
multiple abstractions.)
– Sometimes, it is useful to have greater decoupling
between abstraction and implementation.
– Suppose I have a Shape base class, plus Triangle
and Square derived classes. Now I want to have
them drawn using different graphics libraries.
• Suppose I have three different graphics libraries. How many
subclasses do I need? Solution?
Bridge

• Create a simple API to use between two abstractions.


• Most useful when the concrete implementation of a
higher level abstraction can be specified via a lower-level
abstraction.
• Example:
– class Shape {
virtual void show(…);
…};
class Square : public Shape {
virtual show(…) {
impl->drawLine(…);
impl->drawLine(…);
impl->drawLine(…);
impl->drawLine(…); };
class Triangle : public Shape {
virtual show(…) {
impl->drawLine(…);
impl->drawLine(…);
impl->drawLine(…); };
class GfxImpl { virtual void drawLine(…); …};
class X11GfxImpl : GfxImpl {…};
class GDIGfxImpl : GfxImpl {…};
• Applicability:
– You want to avoid a permanent binding
between abstraction and its implementation.
– Both abstraction and implementations should
be extensible by subclassing.
• Decouples even more interface and
implementation.
• Avoids N*M different classes.
Proxy
(Object Structural)
• Intent
– Provide a surrogate or placeholder for another object to control
access to it.
• Motivation
– Suppose you are writing a web browser. Getting images is slow.
You don’t want to all images are downloaded before starting to
render the page.
• Solution?
• Use a proxy for the image, that can participate in the rendering.
Once the image has downloaded, then fill in.
– Suppose you want to access objects remotely from a client app,
as if they were local:
• MyObject *o = …;
o->method1(); // Actual object should be remote.
• Applicability:
– Remote proxy
– Virtual proxy: defer creation of expensive
objects.
– Protection proxy: control access to an object.
– Smart reference: Do something like copy-on-
write, or reference counting (smart pointers).
• You want to share an implementation among
multiple objects (maybe using reference counting
plus COW).
– You want to hide the implementation from
your users. (C++)
• For example, a remote proxy might represent a
local object on a remote machine.
• Examples
– Suppose you want to be able to invoke remote objects. (Show)
– Suppose you have objects that are usually copied many times
(strings).
– (Show copy on write example.)
– Suppose you have a million Person objects, but you can’t store
all the data about a person in the objects, because it would use
too much space.
• Person::getAge() {
if (impl == 0) {
impl = new PersonImpl(odbc_conn);
}
return impl->getAge();
}
Person::store() { // Called when system decides not needed.
impl->persist();
delete impl;
impl = 0;
}
State (Object Behavioral)
• Intent: Allow an object to alter its behavior
when its internal state changes. The object
will appear to change its class.
– We can do this without using the state
pattern, right?
– Suppose we have a TCPConnection object. It has three
methods: Open(), Close(), Ack(). It also has three states:
Established, Listening, Closed. It behaves differently in response
to the methods depending on what state it is in.
• How do you solve this?
– TCPConnection::Open() {
switch (state) {
case Established: … break;
case Listening: … break;
case Closed: … break;
}
– TCPConnection::Close() {
switch (state) {
case Established: … break;
case Listening: … break;
case Closed: … break;
}
– TCPConnection::Ack() {
switch (state) {
case Established: … break;
case Listening: … break;
case Closed: … break;
}
• Motivation
– Based on Handle/Body.
– A way of allowing an object to change
implementation dynamically. Essentially
changing classes.
– Normally, once an object is created, the
implementation can’t change.
• Connection *conn = new My1Conn;
// Cannot at a later time change to My2Conn.
– How can we make this happen?
• Use a wrapper around an implementation object
that changes as the state changes. Forward all
methods to wrapper.
• Applicability: Use when:
– An object’s behavior depends on its state, and
it must change behavior at run-time
depending on that state.
– Operations have large, multipart conditional
statements to handle the state.
• Rather than have a state variable, and the
implementation check that, just use a completely
different implementation object.
• Example:
– class Connection {
void open() {
conn_state = conn_state->open();
}
};
class UnopenedState : public ConnState {
virtual ConnState *open() {
return new OpenedState(…);
};
};
class OpenedState : public ConnState {
virtual ConnState *open() {
return this;
// Or return error.
};
};
– Connection con; // State starts as
UnopenedState.
con.open(); // Changes state internally.
con.open();
• What’s the alternative, if we don’t use the State
pattern?
– class Connection {
virtual void open() {
if (state == OPEN) {
return;
} else if (state == CLOSED) {
// Do stuff to open.
return;
} else {
abort();
}
}
};
• Consequences:
– Localizes state-specific behavior into a class.
– Makes state transitions very explicit.
– Could essentially change the objects class at
run-time, if the language allowed it.
– The meta-point is that some patterns are to
workaround limitations in static-typed
languages.
Related “Aggregation” Patterns
• Composite
• Facade
• Mediator
Facade (Object Structural)
• Suppose:
– class A {
public:
void method1();
private:
int i;
B b; // Need B.hpp header file?
};
– // client1.cpp
// …
A a;
a.method1();
– // client2.cpp
// …
A a;
a.method1();
– ... // Hundreds of users of A.
– Suppose B is modified. How many files need to be recompiled?
• Some of the apps at Bloomberg take hours to compile.
• Solution?
• Intent
– Provide a unified interface to a set of
interfaces in a subsystem.
– Defines a high level interface that makes the
subsystem easier to use.
• Motivation
– Sometimes you have a set of objects that
make up a subsystem of some kind.
– Now you need to expose the functionality of
that subsystem. How?
• Suppose you are developing an IDE that includes a
compiler:
– Scanner, Parser, ProgramNode, BytecodeStream
• Some clients might need access to these classes directly, but most
do not want this complexity. Most just want to compile.
– Create a single object to represent the subsystem, and hide the
details behind that.
• Applicability
– Provide simple interface to complex system.
Applying patterns can create more classes.
– Too many dependencies between clients and
implementation classes. Gather into one place
with the facade.
– Layer subsystems. Define a facade for each
layer.
– Hide and decouple subsystem from clients.
• Structure
• Example:
– class A {
void detailed_func1();
};
class B {
void detailed_func2();
};
class Facade {
void simple_func1() {
…; a->detailedfunc2(); …; }
void simple_func2() {
…; b->detailedfunc4(); …; }
void simple_func3() {
…; c->detailedfunc1(); …; }
};
• Consequences/benefits
– Shields clients from subsystem components, making
the system easier to use.
– Funnels all interaction from one set of classes to
another set of classes through a single interface,
making it easier to understand the relationship, and
easier to make changes.
• Can also use policy of allowing some direct use if needed.
– Promotes weak coupling between clients and
subsystem, making it easier to change the classes in
the subsystem with affecting the clients.
• Reduces compilation dependencies.
Mediator (Object Behavioral)
• Intent: Define an object that encapsulates how a
set of objects interact. Mediators promote loose
coupling by keeping objects from referring to
each other explicitly, and it lets you vary their
interaction independently of the objects.
• Motivation
– In structured programming, the behavior is “primary”.
You have code that does stuff to data structures. You
break up the behavior into prodedures.
– Object oriented design encourages the distribution of
behavior to the object methods. You divide the
behavior up into methods. Each object has some
methods. The behavior gets distributed.
– Is this good or bad?
– Monster and human fighting. Where does this code
go?
• if (monster_swings) {
if (monster_is_invisible) {

} else {
if (human_limping) {

}
– Often you have a set of objects that interact, but you
don’t really want the encode the interaction patterns
into the objects.
• It can be hard to see what is actually going on, because the
code is scattered around.
– Solution is to use an mediator. You can also think of it
as a coordinator, or manager also.
• Factor out coordination between a set of
objects into a coordinator object.
• Example: Dialog boxes have a lot of
dependencies. For example, if one radio
button is selected, a list box is grayed out.
How do we encapsulate all these
dependencies?
– We could subclass and add to various
methods.
• Example
– Consider an application to handle book purchases.
• Check inventory.
• Check shipping method.
• Authorize credit card.
• Send to shipper.
• Charge credit card.
• Update order information page.
– If you spread out all this logic in the objects, it is hard
to:
• Easily see the steps.
• Easily debug the steps.
• Easily change the steps.
• Easily reuse the objects.
• Contrast with Observer pattern.
– If a particular text box should be grayed when
a radio button is selected, you could make the
text box an Observer of the radio button.
– Compare and contrast.
Chain Based
• Observer
– Notify set of observers when state changes.
• Chain of Responsibility
– Decouple sender of requests from which
object actually handles it.
• Command
– Decouple the code that is responsible for
organizing and firing off commands from the
actual implementation of the command.
Chain Of Responsibility
(Object Behavioral)
• Intent
– Avoid coupling the sender of a request to its receiver by giving
more than one object a chance to handle the request.
– Chain the receiving objects and pass the request along the chain
until an object handles it.
• Motivation
– Consider a context-sensitive help facility. You have buttons
nested inside dialogs, inside applications. The help may be
handled at any level.
– The help that is delivered depends on the part of the interface,
like a button, and the context. For example, an OK button in a
dialog box might have different help from a button in the main
window.
– It’s natural to organize the help information from most specific to
most general. Where it is handled depends on what is available.
• We would like to be able to change the behavior just by changing a
configuration file.
– The problem is that the object that initiates the help doesn’t
know which object is finally going to handle the help.
– Idea is to decouple senders and receivers by giving multiple
objects a chance to handle a request. The request is passed
along a chain.

aSaveDialog
handler anApplication
aPrintButton
handler
handler aPrintDialog
handler
anOKButton
handler
aSaveDialog
handler anApplication
aPrintButton
handler
handler aPrintDialog
handler
anOKButton
handler

– First object either handles it or passes it on. The request has an


implicit receiver.
– What is the sequence diagram if the user clicks on aPrintButton?
• Applicability: Use when
– More than one object may handle a request, and the handler is
not known a priori.
– You want to issue a request to one of several objects without
specifying the receiver explicitly.
– the set of objects that can handle a request should be specified
dynamically.
• Consequences: Benefits and liabilities.
– Reduced coupling.
– Added flexibility in assigning responsibilities. Easy to
do at run-time.
– Receipt is not guaranteed. Could fall of the end.
• Implementation issues:
– Should the chain be done using new links just for this
chain of responsibility, or existing links?
• If there already is a tree, for example, could use just that.
What is the consequence of using an existing set of links?
– Connecting successors:
• Can use a base class that derived classes can
override:
– class HelpHandler {
public:
HelpHandler(HelpHandler *n) : next(n)
{}
virtual void HandleHelp() {
if (next != 0) {
next->HandleHelp();
}
}
private:
HelpHandler *next;
};
– Representing requests
• Could use the method name.
• Could use a single handler function that took a
code.
• Could use a request object.
– void Handler::HandleRequest(Request *req) {
if (typeid(*req) == typeid(PrintRequest)) {
PrintRequest *pr
= dynamic_cast<PrintRequest *>(req);
assert(req != 0);
// …
}
}
Command
(Object Behavioral)
• Intent
– Encapsulate a request as an object, thereby letting you
parameterize clients with different requests, queue or log
requests, and support undoable operations.
– Also bind the action to the receiver. In other words, the object
contains both the action and the recipient of the action.
– An example of how to use a functor.
• Motivation
– Suppose you have a GUI, with menu items. Each menu item has
a different action. But your menu code should be independent of
the actual action.
– Encapsulate the action as a command, which is passed to the
MenuItem when it is created.
– Encapsulate the action as a command.
class PrintAction : public
Action {
Print(Doc *d) : doc(d) {}
class Menu {
virtual void execute() {
void addMenuItem(MenuItem *);
doc->print();
};
}
class MenuItem {
private:
MenuItem(Action *a)
Doc *doc;
: action(a) {}
}
void clicked() {
action->execute();
void NewDoc() {
}
Menu *menu = new Menu;
};
PrintAction *act
class Action {
= new PrintAction(doc);
virtual void execute();
MenuItem *mi
};
= new MenuItem(act);
menu->addItem(mi);
}
• Applicability: Use when you want to
– Parameterize objects (such as the MenuItem)
by the action to perform. Similar to a callback
function, except we are using an object.
– Specify, queue, and execute requests at
different times. Can decouple when the
request was created from when to execute it.
• Suppose your character has been poisoned.
– BadPotion::quaffed() {
PotionEffect *eff
= new BadPotionEffect(severity, delay);
character->queueEffect(eff);
}
Player::TimeStep() {
nextEffect = effects->removeNextEffect();
nextEffect->execute();
}
– Supporting undo. Each command can now
also have an undo() method. You can then
maintain a list of the past N commands.
– Support logging easily. Each command can
write to a log.
• Consequences
– Actions are now first class objects. Can be
subclassed, use multiple-inheritance, etc.
– Commands can be assembled into a
composite command.
– Easy to add new commands. You can do it
without changing your menu system at all, for
example.
• Implementation issues:
– How intelligent/complex should the action be?
• It could actually just do it, or it could call a method
on the receiver.
– PrintAction::execute() {
Printer *p = … ;
PCL *pcl = genPCL(doc);
p->send(pcl);
}
– PrintAction::execute() {
doc->print();
}
• Example
– class Command {
public:
virtual ~Command();
virtual void Execute() = 0;
protected:
Command();
};
class Paste : public Command {
public:
PasteCommand(Doc *);
virtual void Execute();
private:
Doc *doc;
};
void Paste::Execute() { doc->Paste(); }
Miscellaneous
• Flyweight
– Factor out some state into context that is always used
when methods are invoked.
• Memento
– Object persistence
• Singleton
• Strategy
– The “way” to do something is hidden in a strategy
object. For example, how to break up lines.
• Template Method
– The overall “template” of an operation is in the base
class. Some steps are implementation specific, and
handled in derived classes via virtual functions.
Flyweight
(Object Structural)
• Intent
– Use sharing to support large numbers of fine-grained
objects efficiently.
• Motivation
– Suppose you are writing a text editor. It is very
convenient if you can treat every character in the file
as an object.
• Every character has a column, a row, a font, a color, a font
size, a font style.
• How much memory?
– A way of factoring state, as opposed to functionality.
• Separate into extrinsic and intrinsic.
• Operations then need a context.
• Example
– How to avoid storing a lot of properties with each
character.
– class Char {

void draw(const Context &);
char c;
};
class Context {
void setFont(…);
void setColor(…);

};
Char c(‘a’);
Context ctx;
ctx.setFont(…);
c.draw(ctx);
• Variation 1
– Suppose you are writing a game. The game
grid is very fine-grained. Each world has 100
million cells.
– At each cell, there are many properties, like
terrain, weather, etc. Takes 100 bytes each
cell.
– But the terrain is grouped into regions, so two
neighboring cells very likely have the same
terrain.
• A solution
– class Cell {
public:
Terrain *getTerrain() {
return
world->lookupTerrain(x, y); }
private:
int x, y;
};
Terrain *World::lookupTerrain(int x, int y) {
if (x > 50) {
return mountain;
} else {
return plains;
}
}
– So it appears that Terrain is stored with every cell.
Memento
(Object Behavioral)
• Intent
– Snapshot the state of an object into another
object, such that it can be restored easily.
• Example
– class MyClass {
Memento *snapshot();
};
class Memento {
MyClass *restore();
// Or, restore(MyClass *);
};
Singleton
(Object Creational)
• Intent
– Ensure that a class only has one instance, and
provide a global point of access to it.
• Motivation
– Often you will have classes for which there should
only be one instance. For example, if you have a
single node manager in a system, there should only
be one instance of NodeManager.
– A global variable can be used, but doesn’t prevent
you from accidentally creating more than one.
• How to implement this?
– class Singleton {
public:
static Singleton *instance();
protected:
Singleton();
private:
static Singleton *_instance;
};
Singleton *Singleton::instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
– Is this thread safe?
• Implementation:
– May be useful to have a registry of singletons.
– May be useful to allow more than one, but
some limited number.
– How can this be implemented with templates?
Interpreter
(Class Behavioral)
• Intent: Given a language, define a
representation for its grammar along with
an interpreter that uses the representation
to interpret sentences in the language.
• Motivation
– Suppose you have a 3D, fantasy role-playing
game, and you have different magical spells.
• For each spell, you have a different on-screen
animation.
• How would you code this?
• class LightningSpell : public Spell {
virtual void animate() {
extractWand();
raiseArms(/* Height */ 10);
waveArms(/* Speed, Height */ 1, 5);

}
virtual void cast() {
monster = find_hit(direction);
monster->damager();
};
• How convenient is this? How dynamic? How are
bug fixes delivered?
• Options?
– Instead, encode the spell as data to your
program. Then have your program process
the data as commands. This is essentially an
interpeter.
• # In a data file.
spell:
name = lightning
animation = {
extractWand
raiseArms 10
waveArms 1 5 }
• void Action::executeSpell(char *data) {

}
– Other uses for an interpreter?
Summary
• Factory related
– Abstract Factory
• An object with factory methods.
– Factory Method
• A method within an object that is subclassed.
– Builder
• An object to which you feed a sequence of things
to it, then get the result in the end.
– Prototype
• Another way of creating objects via a clone()
method.
– Singleton
• Traversing structures
– Iterator
• Essentially an object that functions as a pointer,or
cursor. It has a current element that it points to,
and methods to advance to the next element.
– Visitor
• For data structures that are heterogeneous. Factor
out the traversal code, and as you traverse the
structure, make callbacks to a visitor object that is
carried along the traversal.
• Wrapper-related
– Adapter
• What if two objects are similar in functionality, but have
different interfaces?
– Bridge
• How do you divide functionality into two layers, so that you
can vary each independently.
– Decorator (same interface)
• A wrapper that adds functionality, but keeps the interface.
– Proxy (same interface)
• A wrapper that “stands-in” for the real thing.
– State
• A wrapper around state-specific implementations. Could be
same interface or not.
• Chain-related
– Observer
• Notify set of observers when state changes.
– Chain of Responsibility
• Decouple sender of requests from which object
actually handles it.
– Command
• Decouple the code that is responsible for
organizing and firing off commands from the actual
implementation of the command.
• Miscellaneous
– Flyweight
• Factor out some state into context that is always used when
methods are invoked.
– Memento
• Object persistence
– Strategy
• The “way” to do something is hidden in a strategy object. For
example, how to break up lines.
– Template Method
• The overall “template” of an operation is in the base class.
Some steps are implementation specific, and handled in
derived classes via virtual functions.
– Interpreter
• Make code no longer hard-coded, but rather move to data,
then execute the data.

You might also like