Saturday, May 31, 2008

Chain of Responsibility

Leave a Comment
What is Chain of Responsibility Pattern?

  • This is a behavioral design pattern.
  • The basic idea behind this pattern is that a request or a command passes through a chain of objects until it is handled.
  • Objects involved in this pattern are of two types. Processing Objects and Command Objects.
  • Processing objects handle the commands given by command objects.
  • Each processing object knows what it can handle and passes the command to the next member in the chain if not handled.
  • A common example to understand this pattern better is the C++ exception handling mechanism. Unhandled exceptions are passed up the call stack until somebody acts upon it.

EXAMPLE: Demonstrate the chain of responsibiltiy behavioral pattern


#include <iostream>
using namespace std;

// STATES
enum ErrorStates { ANALYZE=0, FIX, VERIFY, CLOSE };

// Command Class
class ErrorReport {

private:
ErrorStates state;

public:
ErrorReport(ErrorStates state) {
this->state = state;
}
ErrorStates GetState() {
return state;
}
void SetState(ErrorStates state) {
this->state = state;
}
};

// General base class for all processing objects
class Error {

protected:
ErrorStates state;
Error* successor;

public:
Error(ErrorStates aState) { state = aState; }

void SetSuccessor (Error* error) {
this->successor = error;
}

virtual void ProcessError(ErrorReport& report) = 0;
};

// Processing object class 1 for state ANALYZE
class AnalyzeError : public Error {

public:
AnalyzeError() : Error(ANALYZE) {};

void ProcessError(ErrorReport& report) {
if ( report.GetState() == ANALYZE ) {
cout << "AnalyzeError::Handled the command to analyze the error ..." << endl;
}
else {
cout << "AnalyzeError::Passing to my successor ..." << endl;
successor->ProcessError(report);
}
}
};

// Processing object class 2 for state FIX
class FixError : public Error {

public:
FixError() : Error(FIX) {};

void ProcessError(ErrorReport& report) {
if ( report.GetState() == FIX ) {
cout << "FixError::Handled the command to fix the error ..." << endl;
}
else {
cout << "FixError::Passing to my successor ..." << endl;
successor->ProcessError(report);
}
}
};

// Processing object class 3 for state VERIFY
class VerifyError : public Error {

public:
VerifyError() : Error(VERIFY) {};

void ProcessError(ErrorReport& report) {
if ( report.GetState() == VERIFY ) {
cout << "VerifyError::Handled the command to verify the error ..." << endl;
}
else {
cout << "VerifyError::Passing to my successor ..." << endl;
successor->ProcessError(report);
}
}
};

// Processing object class 4 for state CLOSE
class CloseError : public Error {

public:
CloseError() : Error(CLOSE) {};

void ProcessError(ErrorReport& report) {
if ( report.GetState() == CLOSE ) {
cout << "CloseError::Handled the command to close the error ..." << endl;
}
else {
cout << "VerifyError::No successor ... ignore" << endl;
cout << "No action required ..." << endl;
}
}
};


int main()
{
// Create instances for processing objects
AnalyzeError* analyzeError = new AnalyzeError();
FixError* fixError = new FixError();
VerifyError* verifyError = new VerifyError();
CloseError* closeError = new CloseError();

// Create the chain of responsibility
analyzeError->SetSuccessor(fixError);
fixError->SetSuccessor(verifyError);
verifyError->SetSuccessor(closeError);

// Issue command 1
cout << "--------------- o/p for command 1 ----------------" << endl;
ErrorReport* errorReport1 = new ErrorReport(ANALYZE);
analyzeError->ProcessError(*errorReport1);

// Issue command 2
cout << "--------------- o/p for command 2 ----------------" << endl;
ErrorReport* errorReport2 = new ErrorReport(CLOSE);
analyzeError->ProcessError(*errorReport2);

// Cleanup
delete errorReport2;
delete errorReport1;
delete closeError;
delete verifyError;
delete fixError;
delete analyzeError;
}

OUTPUT:
--------------- o/p for command 1 ----------------
AnalyzeError::Handled the command to analyze the error ...
--------------- o/p for command 2 ----------------
AnalyzeError::Passing to my successor ...
FixError::Passing to my successor ...
VerifyError::Passing to my successor ...
CloseError::Handled the command to close the error ...
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment