Sunday, June 1, 2008

What is Chain of Responsibility Pattern?

  • Chain of Responsibility 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.

Sample Program

#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 ...

0 comments :

Post a Comment

Contact Form

Name

Email *

Message *

Back to Top