Upload
arden-willis
View
39
Download
2
Embed Size (px)
DESCRIPTION
Behavioral Patterns. Chapter 5 – Page 128. Behavioral Pattern: Chain of Responsibility. Chapter 5 – Page 129. On occasion, a system might have more than one mechanism for dealing with requests. - PowerPoint PPT Presentation
Citation preview
Behavioral PatternsC
hap
ter 5
– Pag
e
1
BehavioralPatter
nsDesign
patterns that
identify and realize
common interactions
between objects
Chain of ResponsibilityIntent: Pass requests down a sequence of
receivers until it’s handled.
CommandIntent:
Encapsulate a request as an object so the
request can be invoked when
needed. InterpreterIntent:
Represent the grammar of a
language so its syntax may be
viewed as a composite.
IteratorIntent: Enable the sequential
access of an aggregate object’s
elements without
exposing its structure.Mediator
Intent: Encapsulate the interaction of a set of objects,
preventing them from referring to
each other explicitly.
MementoIntent: Enable an undo capability
without violating
encapsulation.
ObserverIntent: Maintain
a list of dependent
objects, with automatic
updates when one of the objects is updated.
StateIntent: Permit an object to alter its behavior when
its internal state changes.
StrategyIntent:
Encapsulate each algorithm in a family of
algorithms and make them
interchangeable.
Template Method
Intent: Define an algorithm’s basic structure in an
operation, deferring its
details to subclasses.
VisitorIntent: Separate
an algorithm from the
structure of the object on which
it operates.
Behavioral Pattern:Chain of Responsibility
Ch
ap
ter 5
– Pag
e
2
On occasion, a system might have more than one mechanism for dealing with requests.
The Chain of Responsibility pattern sets up the automatic selection of the appropriate mechanism for handling a particular request.By passing the request along the chain until some mechanism handles it, loose coupling is promoted between the mechanisms’ classes .
The Chain of Responsibility Pattern
Ch
ap
ter 5
– Pag
e
3
The Client initiates a request to a ConcreteHandler on the chain.The Handler defines an interface for handling the request and (optionally) implements the successor link.Each ConcreteHandler handles the requests for which it is responsible and can access its successor. If a ConcreteHandler can handle a request, it does so; otherwise it forwards the request to its successor.
ConcreteHandler1
handleRequest()
ConcreteHandler2
handleRequest()
Client Handler
handleRequest() +successor
Ch
ap
ter 5
– Pag
e
4Non-Software Example:ATM WithdrawalThe base ATM class calls the handlers in succession until the requested withdrawal amount is achieved.Each handler repeatedly subtracts its designated amount from the sum requested until that sum exceeds the designated amount.
FranklinHandler
withdrawSum()
GrantHandler
withdrawSum()
ATMUser ATM
withdrawSum() +nextHandlerPointer
JacksonHandler
withdrawSum()
HamiltonHandler
withdrawSum()
LincolnHandler
withdrawSum()
WashingtonHandler
withdrawSum()
while (RequestedSum >= 100){ add $100 bill to sum RequestedSum -= 100}if (RequestedSum == 0) return GoToNext = falseelse return GoToNext = true
The handler indicates to the ATM whether or not the next handler needs to be called.
Ch
ap
ter 5
– Pag
e
5Software Example: CalendarWhen requesting the number of days in a specified month, the 31DayHandler begins the chain, followed by the 30DayHandler, then the FebruaryHandler, and finally the MistakeHandler.
31DayHandler
withdrawSum()
30DayHandler
withdrawSum()
CalendarRequest MonthHandler
daysInMonth() +successorMonthHandler
FebruaryHandler
withdrawSum()
MistakeHandler
withdrawSum()
if (month is January, March, May, July, August, October, or December) return 31else return successorMonthHandler.daysInMonth(month,year)
if (month is April, June, September, or November) return 30else return successorMonthHandler.daysInMonth(month,year)
if (month is February) return 28 or 29 // Depending on the yearelse return successorMonthHandler.daysInMonth(month,year)
return 0
Ch
ap
ter 5
– Pag
e
6Calendar Code in C++#include <iostream>
#include <string>using namespace std;
class MonthHandler { public: MonthHandler() { successorMonthHandler = 0; } void setSuccessor(MonthHandler *smh) { successorMonthHandler = smh; } void add(MonthHandler *mh) { if (successorMonthHandler) successorMonthHandler->add(mh); else successorMonthHandler = mh; } // The "chain" method in the base class always delegates to the next object virtual int numberOfDays(string monthName, int year) { return successorMonthHandler->numberOfDays(monthName, year); } protected: MonthHandler *successorMonthHandler;};
Ch
ap
ter 5
– Pag
e
7class ThirtyOneDayHandler: public MonthHandler { public: int numberOfDays(string monthName, int year) { if ( (monthName == "January") || (monthName == "March") || (monthName == "May") || (monthName == "July") || (monthName == "August") || (monthName == "October") || (monthName == "December") ) return 31; else return successorMonthHandler->numberOfDays(monthName, year); }};
class ThirtyDayHandler: public MonthHandler { public: int numberOfDays(string monthName, int year) { if ( (monthName == "April") || (monthName == "June") || (monthName == "September") || (monthName == "November") ) return 30; else return successorMonthHandler->numberOfDays(monthName, year); }};
Ch
ap
ter 5
– Pag
e
8class FebruaryHandler: public MonthHandler { public: int numberOfDays(string monthName, int year) { if (monthName == "February") if (year % 4 == 0) return 29; else return 28; else return successorMonthHandler->numberOfDays(monthName, year); }};
class MistakeHandler: public MonthHandler { public: int numberOfDays(string monthName, int year) { return 0; }};
Ch
ap
ter 5
– Pag
e
9void main() { string monthName; int year; int nbrOfDays; ThirtyOneDayHandler handler31; ThirtyDayHandler handler30; FebruaryHandler handlerFeb; MistakeHandler handlerMistake; handler31.add(&handler30); handler31.add(&handlerFeb); handler31.add(&handlerMistake); handlerMistake.setSuccessor(&handler31);
cout << "How many days in any given month?" << endl; cout << endl << "Let's find out... " << endl << endl; cout << "Enter a year (use 0 to quit): "; cin >> year; while (year != 0) { cout << "Enter the name of a month: "; cin >> monthName; nbrOfDays = handler31.numberOfDays(monthName, year); if (nbrOfDays != 0) cout << monthName << ' ' << year << " has " << nbrOfDays << " days!" << endl << endl; else cout << "Sorry, but there IS no month called " << monthName << "!!!" << endl << endl; cout << "Want another? Enter a year (use 0 to quit): "; cin >> year; }}
Ch
ap
ter 5
– Pag
e
10
Chain of Responsibility Pattern Advantages
Ch
ap
ter 5
– Pag
e
11
• Chain of Responsibility simplifies object interconnections. Instead of senders and receivers maintaining references to all candidate receivers, each sender keeps a single reference to the head of the chain, and each receiver keeps a single reference to its immediate successor in the chain.• The Chain of Responsibility pattern can be used to deal with long if-then-else statements. A much more descriptive path can be made by coding it into a framework of successive objects that keep a reference to one another in the path, so that a logical path is built by the objects themselves.• The Chain of Responsibility pattern is often used in conjunction with the Composite structural pattern, with a component’s parent acting as its successor.