cse 432: design patterns introduction what’s a pattern? what’s an idiom? according to alexander,...

43
SE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: Describes a recurring problem Describes the core of a solution Is capable of generating many distinct designs An Idiom is more restricted Still describes a recurring problem Provides a more specific solution, with fewer variations Applies only to a narrow context • e.g., the C++ language

Upload: matthew-henderson

Post on 02-Jan-2016

228 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

What’s a Pattern? What’s an Idiom?

• According to Alexander, a pattern:– Describes a recurring problem– Describes the core of a solution– Is capable of generating many distinct designs

• An Idiom is more restricted– Still describes a recurring problem– Provides a more specific solution, with fewer variations– Applies only to a narrow context

• e.g., the C++ language

Page 2: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

“Gang of Four” Pattern Structure

• Gang of Four (GoF): Gamma, Johnson, Helm, Vlissides– Authors of the popular “Design Patterns” book

• A pattern has a name– e.g., the Command pattern

• A pattern documents a recurring problem– Design forces that constrain the solution space– e.g., Issuing requests to objects without knowing in advance what’s to be

requested or of what object

• A pattern describes the core of a solution– e.g., class roles, relationships, and interactions– Important: this is different than describing a design

• A pattern considers consequences of its use– Trade-offs, unresolved forces, other patterns to use

Page 3: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Simple Pattern Form Example: “Singleton”• Problem

– Want to ensure a single instance of a class, shared by all uses throughout a program

• Context– Need to address initialization versus usage ordering

• Solution– Provide a global access method (e.g., a static member

function in C++)– First use of the access method instantiates the class– Constructors for instance can be made private

• Consequences– Object is never created if it’s never used– Object is shared efficiently among all uses

Page 4: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

A More Complete Pattern Form: “Command”• Problem

– Want to issue requests to objects– Don’t know in advance which request(s) will be made– Don’t know in advance to what object(s) they will go

• Solution core– Encapsulate function call parameters and target object

reference inside an “execute” method

• Consequences– Decouples invocation/execution – Commands are first-class objects (elevates functions)– Easy to compose, add new ones

• Example we’ve seen already– STL function objects

Page 5: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Structure Diagram Example: “Command”

• Shows fixed class/interface roles in the pattern• Shows fixed relationships between roles

<<Client>>

<<ConcreteCommand>>

<<Command>><<Invoker>>

<<Receiver>>

action(args)

execute ( )

execute ( )

state_

*

client role command role

inheritance

Page 6: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Collaboration Diagram Example: “Command”• Shows dynamic interactions between pattern roles

– Labels show what interaction does (here, labels show methods called)

• Often used to diagram each of several key scenarios– “Happy path” when everything works, plus different error cases

aCommand anInvokeraClient aReceiver

/ // / / / / /

construct

store

executeaction

time

Page 7: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Idiom Example: Guard

• Problem– Want to tie key scoped behaviors to actual program scopes

• e.g., program trace, resource acquisition/release, locking

– However, tying functions to functions is error-prone• e.g., forgetting the release call, exceptional return paths

• Solution– Design a special adapter class whose constructor and

destructor call the key scope entry and exit behaviors – Create a guard object on the program call stack (in a scope)

• Context limitations– Mainly limited to languages with constructor/destructor

Page 8: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

What is a Pattern Language?

• A pattern resolved some forces– But may leave others unresolved

• Applying additional patterns helps resolve them– Repeat until all forces are resolved

• A well-chosen sequence of patterns– Resolves all design forces adequately– Is some times called “generative”

• Self-consistent, can produce/generate a good design

• A pattern language is a narrative– Of the trade-offs in navigating from requirements to design– Chapters in Pattern Hatching give small pattern languages– This is different than a pattern catalog (the GoF book)

Page 9: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Pattern-Oriented Design• We’ll start by outlining a simple design exercise (Part I)

– Idea: maintain a portfolio of stocks and bonds– Design goals

• Traverse the portfolio and print out each element

• Print out the portfolio in different orders

• Provide a common interface to a single portfolio instance

• Calculate current and projected values of the portfolio

• We’ll see how key patterns drive the design (Part II)– Iterator: access elements sequentially no matter how stored– Factory method: create a related type polymorphically– Singleton: provides access to a single instance– Strategy: makes behaviors pluggable via common interfaces– Adapter: converts an interface you have into one you want– Visitor: allows interaction with heterogeneous collections

• We’ll talk about how we’ve evolved a pattern language (Part III)– Can be reused different design settings where the same issues arise

Page 10: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part I: Design Exercise Outline• Idea: keep track of a portfolio of stocks and bonds

– Abstractly, both stocks and bonds are securities• Each has a name, a number of shares, a current value, and a

projected value

– Stocks and bonds are distinct abstractions, however• Stocks can have a dividend that’s paid out periodically• Bonds can earn interest that’s also paid out periodically

• Design goals– Traverse the portfolio and print out each element– Print out the portfolio in different orders– Provide a common interface to a single portfolio instance– Calculate current and projected values of the portfolio

Page 11: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Basic Abstractions: Security, Stock, Bondstruct Security {

Security (char * name,

int shares,

int current_value,

int projected_value);

virtual ~Security ();

char * name_;

int shares_;

int current_value_;

int projected_value_;

};

struct Stock: public Security { 

Stock (char * name, int shares,

int current_value,

int projected_value,

int dividend);

virtual ~Stock ();  

int dividend_;

};

struct Bond: public Security { Bond (char * name, int shares, int current_value, int projected_value, int interest); virtual ~Bond ();  int interest_;};

Page 12: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Portfolio Abstraction: A Collection of Securitiesclass Portfolio {

  public: 

enum error_condition

{not_found = 1, already_there};

Portfolio ();

virtual ~Portfolio ();

void add (Security *); // takes ownership

void remove (Security *); // releases ownership

void print ();

int current_value (); 

int projected_value ();

  

private:

 

deque<Security *> securities_;

// prevent copy construction, assignment 

Portfolio (const Portfolio &);

Portfolio & operator= (const Portfolio &);

};

Page 13: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part II: Applying Patterns to the Design

• Now we’ll look at how key patterns drive the design forward– Iterator: access elements sequentially no matter how stored– Factory method: create a related type polymorphically– Singleton: provides access to a single instance– Strategy: makes behaviors pluggable via common interfaces– Adapter: converts an interface you have into one you want– Visitor: allows interaction with heterogeneous collections

• Our first challenge is how to iterate through the collection of securities in the portfolio so that we can print out its contents– Motivates use of the Iterator pattern here, in ways that should be familiar– Motivates use of the Factory Method pattern, also in familiar ways

• We’ll look at each of these patterns first• Then we’ll look at code that takes advantage of them

Page 14: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Iterator Pattern• Problem

– Want to access aggregated elements sequentially• E.g., traverse a container of securities and print them out

• Context– Don’t want to know/manage details of how they’re stored

• E.g., could be in a list or an array, but in fact they’re kept in a deque (nicely balances ease of sorting, iteration, addition, and erasure)

• Solution core– Provide an interface for iteration over each container

• Consequences– Frees user from knowing details of how elements are stored– Decouples containers from algorithms (crucial in C++ STL)

• Other examples we’ve seen before– C++ pointers, C++ STL list<int>::iterator

Page 15: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Factory Method Pattern• Problem

– You want a type to create another related type polymorphically– E.g., a container should create appropriate begin and end iterators

• Context– Each type knows which related type it should create

• Solution core– Polymorphic creation– E.g., declare abstract method that derived classes override– E.g., provide traits and common interface as in the STL (what we’ll use)

• Consequences– Type that’s created matches type(s) it’s used with– E.g., appropriately positioned deque<Security *>::iterators are

produced by the deque<Security *> begin() and end() methods

Page 16: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Basic Use of Iterator, Factory Method Patterns

void Portfolio::print () {

for (deque<Security *>::iterator i = securities_.begin();

i != securities_.end(); ++i) {

cout << (*i)->shares_ << " shares of " << (*i)->name_

<< " currently at " << (*i)->current_value_

<< " and projected to be " << (*i)->projected_value_ << endl;

cout << "Current portfolio value: " << current_value() << endl;

cout << "Projected portfolio value: " << projected_value() << endl;

}

• Now onto the next design challenges we’ll address– Only need a single portfolio instance, want easy access to it

– We’ll see how the Singleton pattern helps with this

– Want to sort the portfolio in different ways before printing it– We’ll see how the Strategy and Adapter patterns help with this

Page 17: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Singleton Pattern• Problem

– Want to ensure a single instance of a class, that’s shared by all uses throughout a program (e.g., the Portfolio)

• Context– Need to address initialization versus usage ordering

• Solution core– Provide a global access method (static member function)– First use of the access method instantiates the class– Constructors for instance can be hidden (made private)– Can hide destructor too if a “fini” method is also provided

• Consequences– Object is never created if it’s never used– Object is shared efficiently among all uses

Page 18: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Basic Use of the Singleton Patternclass Portfolio {

public:

static Portfolio * instance();

static void fini(); 

private: 

static Portfolio * instance_;

  Portfolio ();

virtual ~Portfolio ();

};

Portfolio * Portfolio::instance_ = 0;

Portfolio * Portfolio::instance() {

if (instance_ == 0){

instance_ = new Portfolio;

}

return instance_;

}

void Portfolio::fini() {

delete instance_;

instance_ = 0;

}

int main (int, char * []) {  try {  Bond *b = new Bond ("City Infrastructure", 10, 2, 3, 5); Stock *s = new Stock ("Alice's Restaurant", 20, 7, 11, 13); Portfolio::instance()->add (b); Portfolio::instance()->add (s); Portfolio::instance()->print (); Portfolio::fini(); } catch (Portfolio::error_condition &e) { cout << "Portfolio error: " << e << endl; return -1; } catch (...) { cout << "unknown error" << endl; return -2; }  return 0;}

Page 19: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Strategy Pattern• Problem

– Want to plug in a family of alternative parameters to modify behavior (e.g., for sorting the securities before printing them)

• Context– Need a common interface for the family of parameters (e.g.,

less, greater, plus any parameters we want to define)– Need polymorphic substitution of parameter objects

• Solution core– Give the different parameter objects a common interface– Plug these strategies in to modify other behavior (e.g., sort)

• Consequences– Behavior of algorithms (etc.) is easily modified– Can extend family of parameters as needed (see example)

Page 20: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

(Attempted) Basic Use of the Strategy Pattern

struct PrintOrderFunctor {

virtual ~PrintOrderFunctor ();

virtual bool operator () (Security * lhs, Security * rhs) const = 0;

};

void Portfolio::print (PrintOrderFunctor * ppof) {

 

if (ppof) {

sort (securities_.begin(), securities_.end(), *ppof);

}

• We’d like to have something like the code below– Although the top part works, the bottom part doesn’t– STL algorithms take arguments by value (class slicing)– Can’t instantiate PrintOrderFunctor due to pure virtual

• Needs a better way to use the abstract base class

Page 21: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Adapter Pattern• Problem

– We have an interface that’s close to (but not exactly) what we need (cannot use it “as is”)

• Context– Want to re-use an existing class– Can’t change its interface – Impractical to extend class hierarchy more generally

• Solution core– Wrap the interface we have with the interface we need

• Consequences– For a bit more effort, get reuse of what you started with

Page 22: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Basic Use of the Adapter Patternstruct PrintOrderFunctor {

virtual ~PrintOrderFunctor ();

virtual bool operator () (Security * lhs, Security * rhs) const = 0;

};

struct PrintOrderFunctorAdapter {

PrintOrderFunctor &pof_;

PrintOrderFunctorAdapter (PrintOrderFunctor &pof) : pof_(pof) {}

bool operator () (Security * lhs, Security * rhs) {return pof_(lhs, rhs);}

};

void Portfolio::print (PrintOrderFunctor * ppof) {

if (ppof) {PrintOrderFunctorAdapter pofa (*ppof);

sort (securities_.begin(), securities_.end(), pofa);}

• One last design challenge (at least for the moment)– How can we calculate the projected value of the portfolio?

– Need to consider either stock dividend or bond interest– How can we know which is which when traversing the securities?

Page 23: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Visitor Pattern• Problem

– We have a heterogeneous collection of objects over which we need to perform type-specific operations

• Context– Run-time type identification adds overhead and complexity– Want to avoid unnecessary interactions among types – Types in collection change less frequently than the set of

operations that are to be performed over them

• Solution core– Modify types in the collection to support double dispatch

• Consequences– Once modified in this way, any of the types can handshake

with arbitrary “visitors” to give correct behavior

Page 24: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Basic Use of the Visitor Patternstruct SecurityVisitor {

virtual ~SecurityVisitor();

virtual void

visit_stock (Stock *) = 0;

virtual void

visit_bond (Bond *) = 0;

};

struct Security {

… 

virtual void

accept (SecurityVisitor * sv) = 0;

};

void

Stock::accept (SecurityVisitor * sv) {

if (sv) {sv->visit_stock(this);}

}

void

Bond::accept (SecurityVisitor * sv) {

if (sv) {sv->visit_bond(this);}

}

struct ProjectedValueFunctor : public SecurityVisitor { int & value_; ProjectedValueFunctor (int & value); virtual ~ProjectedValueFunctor (); void operator () (Security * s) { s->accept(this); } virtual void visit_stock (Stock * s) { if (s) {value_ += s->shares_ * (s->projected_value_ + s->dividend_);} } virtual void visit_bond (Bond * b) { if (b) {value_ += b->shares_ * (b->projected_value_ + b->interest_);} }};

int Portfolio::projected_value () { int value = 0; for_each (securities_.begin(), securities_.end(), ProjectedValueFunctor(value)); return value;}

Page 25: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part III: A Design Pattern Language• We’ve now evolved what’s called a “pattern language”

– A recurring sequence of design patterns that can be applied to solve a recurring sequence of design challenges each time you see it

– To identify such pattern languages, look for repetition not only of individual patterns, but also of combinations and sequences of patterns

– Then, look for repetition of the design problems, and apply the language

• This pattern language can be reused when same issues arise– E.g., any design involving a single collection of heterogeneous elements– E.g., instead of a portfolio of stocks and bonds, a zoo of zebras and

birds

• In parts IV to VI we’ll evolve another design pattern language– To address additional challenges raised by multiple interacting agents– We’ll apply the pattern language to further extend today’s design– We’ll add multiple agents, each with their own portfolio– We’ll add (closed agent-to-agent) cross trading of securities among them– We’ll add a market to mediate event triggered open trading of securities

Page 26: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

From Patterns to Pattern Languages

• So far we’ve looked at pattern-oriented software design– We looked for key challenges at each step of the design process– We matched each challenge with a suitable design pattern– The pattern let us overcome that challenge and move on to the next one

• This lecture will take that same approach– New focus: additional design issues related to multi-agent interactions– A fresh look at the Singleton pattern– New design patterns (from Gamma et al.)

• We’ll talk about how sets of patterns are combined/navigated– A look back at the design patterns we’ve used this week

Page 27: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Developing (and Using) a 2nd Pattern Language• We’ll further extend our design from last time (Part I)

– Idea: add “agents” who trade stocks and bonds– Design goals

• Allow multiple agents, each with their own portfolio, who can trade directly

• Allow agents to enter and leave the group of agents currently trading

• Add a market to mediate event triggered open trading of securities

• We’ll see again how key patterns drive the design (Part II)– Singleton variant: provides key-discriminated access to a single instance– Prototype: a type can produce a duplicate instance of the same type– Memento: package up object state without violating encapsulation– Command: encapsulates a future function call inside a functor– Observer: tell registered observers when state changes

• We’ll see how we’ve evolved another pattern language (Part III)– Can be reused in different design settings where the same issues arise– I.e., many with interacting agents (interestingly, even distributed ones)

Page 28: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part IV: Design Exercise Outline• Idea: add “agents” who trade stocks and bonds

– We define an “agent” as a potentially independently acting software entity (software engineering notion rather than AI)

– Shifts the focus from a single portfolio to the group of agents

• Design goals– Allow multiple agents, each with their own portfolio

• Support (closed agent-to-agent) cross trading of securities• Need to consider all of the common data (shares, current and

projected values, name) when testing securities for equivalence• Assume trades are for all (or none) of the shares in a security object

– Add a market to mediate (event triggered) open trading– Allow agents to enter and leave the group that’s trading

• I.e., they can save and restore their portfolio and their reserve

Page 29: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part V: Applying Patterns to the Design

• First challenge: each agent needs their own portfolio– Don’t let an agent access another’s portfolio (security)– However, want to keep previous benefits of using singleton

• Reconsider how we have applied the Singleton pattern– Need to maintain a separate portfolio instance per agent– First access by an agent still creates their specific portfolio– Still want a single global access method, but index into it

• We’ll use each agent’s memory address as the index key• Simplifying assumption: Agents’ memory locations are hard to infer

– Not true actually: probe k*sizeof(Agent) bytes away from this– In practice you’d use cryptographic keys instead for secure indexing

Page 30: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

New Variation of the Singleton Patternclass Portfolio {

public:

static Portfolio * instance(Agent *);

static void fini(Agent *);

...

private: 

static map<Agent *, Portfolio *> instances_;

Portfolio ();

virtual ~Portfolio ();

...

};

map<Agent *, Portfolio *> Portfolio::instances_;

Portfolio * Portfolio::instance(Agent *a) {

Portfolio * p = 0;

map<Agent *, Portfolio *>::iterator i =

instances_.find(a);

if (i == instances_.end()) {

p = new Portfolio;

instances_.insert(make_pair(a,p));

} else { p = i->second; }

return p;

}

void Portfolio::fini(Agent *a) { map<Agent*,Portfolio*>:: iterator i = instances_.find(a); if (i != instances_.end()) { Portfolio * p = i->second; instances_.erase(i); delete p; }}

void Agent::buy (Security *s) { int cost = s->shares_ * s->current_value_; if (cost > reserve_) { throw cannot_afford; }Portfolio::instance(this)-> add(s); reserve_ -= cost; }

Agent::~Agent () { Portfolio::fini(this);}

Page 31: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Buying and Selling Securities• Second challenge: how to duplicate securities

– We distinguish securities by their common data but not by their concrete types (or type-specific data)

– I.e., we encapsulate whether a security is a stock or bond• I.e., use visitor to handshake with it as needed, otherwise don’t care

– What if we need to give away a new instance?• If we don’t know a security’s type, do we create a stock or a bond?

– Could rewrite portfolio’s remove method to work around this• Remove the security and return a pointer to it rather than destroying it• However, may want this later (say for extension to sell part of shares)

• Motivates use of the Prototype pattern– Creates an instance of the original type, polymorphically

• Similar in idea and implementation to Factory Method pattern

– Emulates virtual copy constructor (C++ doesn’t have that)

Page 32: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Prototype Pattern• Problem

– Need to duplicate objects with different dynamic types

• Context– Virtual constructors are not available (e.g., in C++)– However, polymorphic method invocations are supported

• Solution core– Provide a polymorphic method that returns an instance of

the same type as the object on which the method is called– Polymorphic method calls copy constructor, returns base

class pointer or reference to concrete derived type

• Consequences– Emulates virtual copy construction behavior– Allows anonymous duplication of heterogeneous types

Page 33: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Use of the Prototype Pattern

struct Security {

public:

virtual Security * clone () = 0;

...

};

Security * Stock::clone () {

return new Stock(*this);

}

Security * Bond::clone () {

return new Bond(*this);

}

Security * Agent::sell (Security *s) {

Security * current = Portfolio::instance(this)->find(s);

if (current ==0) { throw cannot_provide; }

Security * copy = current->clone();

Portfolio::instance(this)->remove(current);

reserve_ += copy->shares_ * copy->current_value_;

return copy;}

Page 34: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Adding State Persistence

• Third challenge: allow agents to depart and return– Need to save and restore agent’s portfolio and reserve– Let agent serialize state to/from a persistent file, map, etc.

• We’ll only implement the save part for now• Restore may draw on other patterns we won’t cover (e.g., interpreter)

• Motivates use of the Memento pattern– Serializes agent’s portfolio and reserve into opaque “cookie”– Format of cookie can be tailored to storage format

• Also Motivates use of the Command pattern– Encapsulates actions on objects within a functor– Here, provides a different kind of double dispatch to collect

strings representing the states of individual securities

Page 35: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Memento Pattern• Problem

– Want to externalize state of an object without violating encapsulation

• Context– A snapshot of object state is needed– Providing a state interface would violate encapsulation

• Solution Core– Create a memento class with methods to get, set state– Provide an opaque representation of state itself

• Consequences– Can use memento to send object state over a socket,– save it in a file, put it into a checkpoint/undo stack, etc.

Page 36: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Command Pattern• Problem

– Want to issue requests to objects

• Context– Don’t know in advance which request(s) will be made– Don’t know in advance to what object(s) they will go

• Solution core– Encapsulate function call parameters and target object

reference inside an “execute” method

• Consequences– Decouples invocation/execution – Commands are first-class objects (generalizes functions)– Easy to compose existing ones, or add new ones

• Example we’ve seen already– STL function objects

Page 37: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Use of the Memento and Command Patternsstruct Security {

...

virtual string memento () = 0;

...

};

string Stock::memento () {

ostringstream oss;

oss << "STOCK " << name_ << " " << shares_

<< " " << current_value_ << " "

<< projected_value_ << " " << dividend_;

string s = oss.str() + "\n";

return s;

}

string Bond::memento () {

ostringstream oss;

oss << "BOND " << name_ << " " << shares_

<< " " << current_value_ << " “

<< projected_value_ << " " << interest_;

string s = oss.str() + "\n";

return s;

}

struct MementoFunctor { string &str_; MementoFunctor (string &str) : str_(str) {} void operator () (Security * sec){ str_ += sec->memento(); }};

string Portfolio::memento () { string s; for_each (securities_.begin(), securities_.end(), MementoFunctor(s)); return s; }

string Agent::memento () { ostringstream oss; oss << name_ << " " << reserve_; string s = oss.str() + "\n" + Portfolio::instance(this)-> memento(); return s; }

Page 38: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Use of the Memento Pattern, Continued

class Caretaker {

public:

static Caretaker * instance();

void save_me(Agent *a);

void restore_me(Agent *a);

private:

Caretaker ();

~Caretaker ();

map<const char *, string> mementos_;

static Caretaker * instance_;

};

void Caretaker::save_me(Agent *a) {

if (a == 0) return;

map<const char *, string>::iterator i = mementos_.find(a->name());

if (i == mementos_.end()) { mementos_.insert(make_pair(a->name(), a->memento())); } else { i->second = a->memento(); }}

void Agent::save() { Caretaker::instance()->save_me(this);}

void Agent::restore() { Caretaker::instance()->restore_me(this);}

Page 39: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Adding a Market

• Fourth challenge: need to coordinate market, agents– Agents independently choose when (and whether) to trade– Whenever a trade is made in the market, agents are notified

• Motivates use of the Observer pattern– Helps to keep agents independent– Separates registration, notification, trading interactions – Allows coordination between market and the agents

Page 40: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Observer Pattern• Problem

– Need to update multiple objects when the state of one object changes

• Context– Multiple objects depend on the state of one object

– Set of dependent objects may change at run-time

• Solution core– Allow dependent objects to register with object of interest,

notify them of updates when state changes

• Consequences– When observed object changes others are notified

– Useful for user interface programming, other applications

Page 41: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Use of the Observer Patternclass Market {

public:

static Market * instance();

void bind(Agent *);

void unbind(Agent *);

void make_advertisement();

void fetch_advertisements();

private:

...

void notify ();

set<Agent *> observers_;

};

void Market::bind(Agent *a) {

set<Agent *>::iterator i = observers_.find(a);

if (i == observers_.end()) {observers_.insert(a);}

}

void Market::unbind(Agent *a) {

set<Agent *>::iterator i = observers_.find(a);

if (i != observers_.end())

{observers_.erase(i);}

}

void Market::make_advertisement() { notify();}

void Market::fetch_advertisements() { ... }

void Market::notify () { for (set<Agent *>::iterator i = observers_.begin(); i != observers_.end(); ++i) { (*i)->update(); }}

Agent::Agent (const char * name, int reserve) : name_(name), reserve_(reserve) { Market::instance()->bind(this);}

Agent::~Agent () { Market::instance()->unbind(this); Portfolio::fini(this);}

void Agent::update() { Market::instance()->fetch_advertisements();}

Page 42: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Part VI: 2nd Design Pattern Language• We’ve evolved another pattern language

– A recurring sequence of design patterns that can be applied to solve a recurring sequence of design challenges each time you see it

• Think of the patterns as a “design vocabulary” that you can use– E.g., combine command, proxy, and memento to serialize an object,

send it from one computer to another across a socket, re-constitute it

• This pattern language can be reused when same issues arise– E.g., designs for multiple interacting agents with similar requirements– E.g., instead of agents and a market, client and server computers

• Gamma et al. (GoF Book) takes this idea of reuse even farther– Shows how the patterns can be collected into a design evolution map– Describes how the resulting “pattern map” can be reused

Page 43: CSE 432: Design Patterns Introduction What’s a Pattern? What’s an Idiom? According to Alexander, a pattern: –Describes a recurring problem –Describes the

CSE 432: Design Patterns Introduction

Summary• We’ve now looked at quite a few patterns

– Iterator: access elements sequentially no matter how stored

– Factory method: create a related type polymorphically

– Singleton: provides access to a single instance (possibly per index)

– Strategy: makes behaviors pluggable via common interfaces

– Adapter: converts an interface you have into one you want

– Visitor: allows interaction with heterogeneous collections

– Prototype: allows polymorphic duplication of heterogeneous types

– Memento: packages up object state without violating encapsulation

– Command: packages up a function as an object– Observer: tell registered observers when state changes

• More importantly we’ve looked at how they can drive design– From basic abstractions towards a working program (despite obstacles)– A “design vocabulary” and related sequences within it

• CSE 432 focuses on combining patterns of this sort (design)• CSE 532 focuses on other kinds of patterns (architectural)