COSC 3351 Software Design

Design Patterns Behavioral Patterns (II)

Edgar Gabriel Spring 2008

Edgar Gabriel

Purpose Creational Structural Behavioral Scope Class Factory Method Adapter(class) Interpreter Template Method Object Abstract Factory Adapter(object) Chain of Responsibility Builder Bridge Command Prototype Composite Singleton Decorator Mediator Façade Observer Flyweight State Proxy Strategy Visitor Memento

COSC 3351 – Software Design Edgar Gabriel

1 Memento

• Intent : Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later. • Applicability : Use the when – A snapshot of an object’s state must be saved so that it can be restored to that state later, and – A direct interface to obtaining the state would expose implementation details and break the object’s encapsulation

COSC 3351 – Software Design Edgar Gabriel

Structure

Originator Memento Caretaker

state state

SetMemento(Memento m) GetState() CreateMemento() SetState()

state = m->GetState();

return new Memento(state);

COSC 3351 – Software Design Edgar Gabriel

2 Participants

• Memento: – stores internal state of the Originator object – protects against access by objects other than the originator • Originator: – creates a memento containing a snapshot of its current internal state – uses the memento to restore its internal state • Caretaker: – is responsible for the memento’s safekeeping – never operates on or examines the contents of a memento

COSC 3351 – Software Design Edgar Gabriel

Implementation

• Mementos have two interfaces: – a wide one for the originators: C++ usually relies on making the Originator a friend of Memento + making Memento’s wide interface private – a narrow one for other objects: public interface

COSC 3351 – Software Design Edgar Gabriel

3 class Originator { public: Memento* CreateMement(); void* SetMemento( const Memento* ); private: State* _state; } class Memento { public: // narrow public interface virtual ~Memento(); private: friend class Originator; Memento(); void SetState(State *); State* GetState(); private: State* _state; }

COSC 3351 – Software Design Edgar Gabriel

// implementation of the Do() and Undo() operations of // the Originator, assuming that it confirms to the command // pattern void Originator::Do() { Originator* ori = Originator::Instance(); _state = ori->CreateMemento(); // do whatever the code has to do } void Originator::Undo() { Originator *ori = Originator::Instance(); ori->SetMemento(_state); … }

COSC 3351 – Software Design Edgar Gabriel

4 State

• Intent : allow an object to alter its behavior when its internal state changes. The object will appear to change its class. • Applicability : use the when – an object’s behavior depends on its state, and it must change its behavior at run-time depending on the state. – Operations have large, multipart conditional statements • Advantages : – Localizes state-specific behavior and partitions behavior for different states – It makes state transition explicit – State objects can be shared

COSC 3351 – Software Design Edgar Gabriel

Structure

Context <> State

Request() Handle()

state->Handle(); ConcreteStateA ConcreteStateB

Handle() Handle()

COSC 3351 – Software Design Edgar Gabriel

5 Participants

• Context: – Define the interface of interest to clients – Maintains an instance of a ConcreteState subclass that defines the current state • State: – Defines an interface for encapsulating the behavior associated with a particular state of the Context • ConcreteState: – Each subclass implements a behavior associated with a state of the Context.

COSC 3351 – Software Design Edgar Gabriel

Example: TCP connection

COSC 3351 – Software Design Edgar Gabriel

6 class TCPOctetStream; class TCPState;

class TCPConnection { public: TCPConnection(); void ActiveOpen(); void PassiveOpen(); void Close(); void Send(); void Acknowledge(); void Synchronize();

void ProcessOctet(TCPOctetStream* ); private: friend class TCPState; void ChangeState (TCPState *); private: TCPState* _state; }

COSC 3351 – Software Design Edgar Gabriel

• TCPState duplicates the state-changing interface of TCPConnection – each method takes an additional TCPConnection instance as a parameter can therefore access Data from TCPConnection and modify the state class TCPState { public: virtual void Transmit(TCPConnection*, TCPOctetStream*) virtual void ActiveOpen(TCPConnection* ); virtual void PassiveOpen(TCPConnection*); virtual void Close(TCPConnection*); virtual void Send(TCPConnection*); virtual void Acknowledge(TCPConnection*); virtual void Synchronize(TCPConnection*);

protected: void ChangeState (TCPConnection*, TCPState *); } // provide default implementations for all classes, e.g. void TCPState::Transmit(TCPConnection*, TCPOctetStream*) {} void ActiveOpen(TCPConnection* ) {} void PassiveOpen(TCPConnection*) {} void Close(TCPConnection*) {} COSC 3351 – Software Design voidEdgar Gabriel Send(TCPConnection*) {}

7 TCPConnection::TCPConnection() { _state = TCPClosed::Instance(); } void TCPConnection::ChangeState(TCPState *s ) { _state = s; } void TCPConnection::ActiveOpen() { _state->ActiveOpen(this); } void TCPConnection::PassiveOpen() { _state->PassiveOpen(this); } void TCPConnection::Close() { _state->Close(this); } void TCPConnection::Acknowledge() { _state->Acknowledge(this); } void TCPConnection::Synchronize() { _state->Synchronize(this); }

COSC 3351 – Software Design Edgar Gabriel

class TCPEstablished:: public TCPState { public: static TCPState* Instance(); virtual void Transmit(TCPConnection*, TCPOctetStream*); virtual void Close(TCPConnection*); }; class TCPListen:: public TCPState { public: static TCPState* Instance(); virtual void Send (TCPConnection*); … } void TCPEstablished:: Close ( TCPConnection *s ) { // send FIN // receive ACK ChangeState ( s, TCPListen::Instance() ); } void TCPEstablished::Transmit (TCPConnection *s, TCPOctetstream *o ) { s->ProcessOctet(o); // this function does not change the state } COSC 3351 – Software Design Edgar Gabriel

8 Strategy

• Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. • Applicability: use the when – many related classes differ only in the behavior – you need different variants of an algorithm – you want to avoid to expose complex, algorithm-specific data structures – a class defines many behaviors, and these appear as multiple conditional statements in the operation.

COSC 3351 – Software Design Edgar Gabriel

Structure

Context <> Strategy

Contextinterface() Algorithminterface()

ConcreteStrategyA ConcreteStrategyB

Algorithminterface() Algorithminterface()

COSC 3351 – Software Design Edgar Gabriel

9 Participants

• Strategy: declares an interface common to all supported algorithms • ConcreteStrategy: implements the algorithm using the Strategy interface • Context: – is configured with a ConcreteStrategy object, i.e. the Constructor takes a ConcreteStrategy object – maintains a reference to a Strategy object – may define an interface that lets Strategy accesss data

COSC 3351 – Software Design Edgar Gabriel

Visitor • Intent : Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates • Applicability : Use the when – an object structure contains many classes of objects with differing interfaces and you want to perform operations on these objects that depend on their concrete classes – many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid ‘polluting’ the classes with these operations – the classes defining the object structure changes rarely, but you often want to define new operations on the structure COSC 3351 – Software Design Edgar Gabriel

10 Structure

<> Client Visitor

VisitorConcreteElementA() VisitorConcreteElementB()

ConcreteVisitorA ConcreteVisitorB

VisitorConcreteElementA () VisitorConcreteElementA() VisitorConcreteElementB () VisitorConcreteElementB()

<> ObjectStructure Element

Accept(Visitor)

ConcreteElementA ConcreteElementB

v->VisitorConcreteElementA(this); Accept (Visitor v) Accept (Visitor v) OperationA() OperationB()

COSC 3351 – Software Design Edgar Gabriel

Participants

• Visitor : declares a Visit operation for each ConcreteElement in the object structure • ConcreteVisitor : implements each operation declared by Visitor • Element : defines an Accept operation that takes a visitor as an argument • ConcreteElement : implements an Accept operation that takes a visitor as an Argument • ObjectStructure: – Can enumerate its elements – May provide a high-level interface to allow the visitor to visit its elements – May either be a composite or a collection such as a list or a set

COSC 3351 – Software Design Edgar Gabriel

11 Consequences

• Visitor makes adding new operations easy • Adding a new ConcreteElement is hard, since you have to update all ConcreteVisitor classes • The visitor pattern depends on : the method calls depends on the Visitor and the Element.

COSC 3351 – Software Design Edgar Gabriel

class Visitor { public: virtual void VisitElementA(ElementA *); virtual void VisitElementA(ElementA *); protected: Visitor(); }

class Element { public: virtual ~Element(); virtual void Accept(Visitor&) =0; protected: Element(); } class ElementA : public Element { public: ElementA(); virtual void Accept(Visitor& v){ v.VisitElementA(this);} } class ElementB : public Element { public: ElementB(); virtual void Accept(Visitor& v){ v.VisitElementB(this);} }

COSC 3351 – Software Design Edgar Gabriel

12 // Example for a composite element class CompositeElement : public Element { public: CompositeElement(); virtual void Accept(Visitor&); private: List* _children; }

void CompositeElement ::Accept (Visitor &v) { ListIterator i(_children);

for ( i.First(); !i.IsDone(); i.Next() ){ i.CurrentItem()->Accept(v); }

v.VisitCompositeElement(this);} } COSC 3351 – Software Design Edgar Gabriel

Discussion of Behavioral Patterns

• Mediator and Observer are competing patterns – Mediator encapsulates interactions • easier to understand dependencies and logical flow • Mediators are hardly ever reusable – Observer distributes communication between objects • more difficult to understand to understand the flow of communication • easier to write reusable subjects and oberservers

COSC 3351 – Software Design Edgar Gabriel

13 Discussion of Behavioral Patterns

• Decoupling of Sender and Receiver – Command: introduces a Command class between invoker and Receiver – Observer: decouples senders ( subjects) from receivers (observers) by defining an interface for signaling changes in subjects. Observer objects and number of observers can however vary at runtime – Mediator: decouples senders and receivers by not having direct references to each other, but only through the mediator – Chain of Responsibility: passes requests along a chain of potential receivers.

COSC 3351 – Software Design Edgar Gabriel

Summary of

• Design Patterns do not present – new algorithms – new programming techniques – new methods for designing systems – new theories for design • Design Patterns do – document established approaches – present a uniform language to describe these approaches – can help to cut down development time, since you do not have to reinvent the wheel for many scenarios.

COSC 3351 – Software Design Edgar Gabriel

14