behavioral pattern: strategy

12
Behavioral Pattern: Strategy Chapter 5 – Page 1 The Open-Closed Principle advocates designing software in such a way that it will absorb new variations without having to introduce new fundamental structure, enabling the capabilities of a system to be extended without substantially changing the basic system. The Strategy Pattern attempts to accomplish this by encapsulating each algorithm in a family of algorithms and making them all interchangeable, thus allowing each algorithm to vary independently of the clients that use it. This permits a program to switch easily between algorithms without resorting to monolithic if-else statements. This approach allows the behavior in question to be modified at run-time and not just at design time.

Upload: javan

Post on 20-Feb-2016

34 views

Category:

Documents


1 download

DESCRIPTION

Behavioral Pattern: Strategy. Chapter 5 – Page 205. - PowerPoint PPT Presentation

TRANSCRIPT

Behavioral Pattern: StrategyChapter 5 – Page 1The Open-Closed Principle advocates designing software in such a way that it will absorb new variations without having to introduce new fundamental structure, enabling the capabilities of a system to be extended without substantially changing the basic system.The Strategy Pattern attempts to accomplish this by encapsulating each algorithm in a family of algorithms and making them all interchangeable, thus allowing each algorithm to vary independently of the clients that use it.This permits a program to switch

easily between algorithms without resorting to monolithic if-else statements.This approach allows the behavior in question to be modified at run-time and not just at design time.

The Strategy PatternChapter 5 – Page 2

The Strategy declares an interface common to all supported algorithms, using this interface to call the algorithm defined by a ConcreteStrategy.The ConcreteStrategy implements the algorithm using the Strategy interface.The Context is configured with a ConcreteStrategy object, maintains a reference to a Strategy object, and may define an interface that lets the Strategy object access its data.

ConcreteStrategyA

AlgorithmInterface()

ConcreteStrategyB

AlgorithmInterface()

ConcreteStrategyC

AlgorithmInterface()

Strategy

AlgorithmInterface()

Context

ContextInterface()

+strategy

Chapter 5 – Page 3Non-Software Example:Airport TransportationModes of transportation to an airport is an example of a Strategy.

PersonalVehicle

Transport()

Taxicab

Transport()

Limousine

Transport()

Strategy

Transport()

AirportTransportation

GoToAirport(Time, Cost)

+strategy

HotelShuttleBus

Transport()

Several options exist, such as driving one's own car, taking a taxi, an airport shuttle, or a limousine service.For some airports, subways and helicopters are also available as a mode of transportation to the airport.Any of these modes of transportation will get a traveler to the airport, and they can be used interchangeably.The traveler must chose the Strategy based on tradeoffs between cost, convenience, and time.

Chapter 5 – Page 4Software Example: Event HandlerThe NetworkManagement context needs strategies for handling various events on the network.The Connection strategy is to respond by indicating a need for greater bandwidth. Path

HandleEvent()

Connection

HandleEvent()

LSPlspID

HandleEvent()

NetworkManagementEventHandlercurrentEvent

HandleEvent()

+strategy

+successor

The Path strategy is to respond by indicating a need for some alternative path through the network.The LSP strategy is to respond by indicating a need for an alternative path through the network that meets specific label switched path requirements.(Note that this model utilizes both the Strategy Pattern and the Chain of Responsibility Pattern.)

Chapter 5 – Page 5Event Handler Strategy C++ Code#include <iostream>#include <string>using namespace std;

typedef int Event;const Event LINK_1_BROKEN = 1;const Event LINK_2_BROKEN = 2;const Event CONGESTION = 3;const Event No_Event_Support = -1;

class EventHandler{ public: explicit EventHandler(EventHandler* hdlr = 0, Event evt = No_Event_Support); virtual const bool HasEventSupport(Event evt); virtual void SetHandler(EventHandler* hdlr, Event evt); virtual void HandleEvent(Event evt); virtual ~EventHandler() { cout << "Now in the EventHandler destructor" << endl; }; private: EventHandler* successor; Event currentEvent;};

Chapter 5 – Page 6

//Set up a chain of event handlersEventHandler::EventHandler( EventHandler* hdlr, Event evt ) : successor(hdlr), currentEvent(evt) { }

const bool EventHandler::HasEventSupport(Event incomingEvent) { return currentEvent == incomingEvent;}

void EventHandler::SetHandler(EventHandler* hdlr, Event evt){ successor = hdlr; currentEvent = evt;}

void EventHandler::HandleEvent (Event incomingEvent){ if (incomingEvent != currentEvent) { if (successor != 0) { cout << "HandleEvent () calling into successor" << endl; successor->HandleEvent(incomingEvent); } } else { cout << "Base class help now follows" << endl; }}

Chapter 5 – Page 7

class Connection : public EventHandler { public: Connection(Event evt) : EventHandler(0, evt) { } virtual void HandleEvent(Event incomingEvent);};

void Connection::HandleEvent(Event incomingEvent){ if (HasEventSupport(incomingEvent)) { // Offer event support cout << "Here's some Connection Event support" << endl; cout << "You may need additional bandwidth" << endl << endl; } else { cout << "No support from Connection - Sorry!" << endl; cout << "Calling the base class event handler" << endl; EventHandler::HandleEvent(incomingEvent); }}

Chapter 5 – Page 8

class Path : public Connection{ public: Path::Path(Connection* conx, Event evt) : Connection(0) { cout << "In the Path constructor" << endl; SetHandler(conx, evt); }

void HandleEvent(Event incomingEvent) { if (HasEventSupport(incomingEvent)) { // Offer event support cout << "Here's some Path Event support" << endl; cout << "We need a new path" << endl << endl; } else { cout << "No support from Path - Sorry!" << endl; cout << "Calling the base class event handler" << endl; EventHandler::HandleEvent(incomingEvent); } }};

Chapter 5 – Page 9

class Lsp : public Connection { public: Lsp::Lsp(string lspID, Connection* conx, Event evt) : Connection(0) { cout << "Constructing Lsp: " << lspID << endl; lspName = lspID; SetHandler(conx, evt); }

void HandleEvent(Event incomingEvent) { if (HasEventSupport(incomingEvent)) { // Offer event support cout << "At last, here's some LSP Event support:" << endl; cout << "We need an alternative path for " << lspName << endl << endl; } else EventHandler::HandleEvent(incomingEvent); }

private: string lspName;};

Chapter 5 – Page 10void main()

{ // Set up a Path->LSP->Connection Chain of Responsibility Connection* connection = new Connection(CONGESTION); Lsp* lsp = new Lsp("LSP123", connection, LINK_1_BROKEN); Path* path = new Path(lsp, LINK_2_BROKEN); cout << endl << "Time to handle network events" << endl << endl;

//A network event has occurred, e.g., CONGESTION //Let's see who can handle this event cout << "Let's simulate a network error: CONGESTION" << endl; path->HandleEvent(CONGESTION);

//Another network event has occurred, e.g., LINK_1_BROKEN //Let's see who can handle this event cout << "Let's simulate another network error: LINK_1_BROKEN" << endl; path->HandleEvent(LINK_1_BROKEN);

cout << "Let's simulate one more network error: LINK_2_BROKEN" << endl; path->HandleEvent(LINK_2_BROKEN);

delete path; delete lsp; delete connection;}

Chapter 5 – Page 11

Strategy Pattern AdvantagesChapter 5 – Page 12• With the Strategy Pattern, a family of algorithms

can be defined as a class hierarchy and can be used interchangeably to alter an application’s behavior without changing its architecture.

• By encapsulating the algorithm separately, new algorithms complying with the same interface can easily be introduced.• The application can switch strategies at run-time, and clients can choose the required algorithm without using a “switch” statement or a series of “if-else” statements.• Data structures used for implementing the algorithm are completely encapsulated in Strategy classes, so the implementation of an algorithm can be changed without affecting the Context class.