StackStalk
  • Home
  • Java
    • Java Collection
    • Spring Boot Collection
  • Python
    • Python Collection
  • C++
    • C++ Collection
    • Progamming Problems
    • Algorithms
    • Data Structures
    • Design Patterns
  • General
    • Tips and Tricks

Saturday, May 31, 2008

C++ Chain of Responsibility Design Pattern

 May 31, 2008     Design Patterns     No comments   

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. In this article we will explore basics of Chain of Responsibility Design Pattern with sample implementation in C++.

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

Chain of Responsibility Pattern implementation

#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 ...
  • Share This:  
Newer Post Older Post Home

0 comments:

Post a Comment

Follow @StackStalk
Get new posts by email:
Powered by follow.it

Popular Posts

  • Avro Producer and Consumer with Python using Confluent Kafka
    In this article, we will understand Avro a popular data serialization format in streaming data applications and develop a simple Avro Produc...
  • Monitor Spring Boot App with Micrometer and Prometheus
    Modern distributed applications typically have multiple microservices working together. Ability to monitor and manage aspects like health, m...
  • Server-Sent Events with Spring WebFlux
    In this article we will review the concepts of server-sent events and work on an example using WebFlux. Before getting into this article it ...
  • Implement caching in a Spring Boot microservice using Redis
    In this article we will explore how to use Redis as a data cache for a Spring Boot microservice using PostgreSQL as the database. Idea is to...
  • Python FastAPI microservice with Okta and OPA
    Authentication (AuthN) and Authorization (AuthZ) is a common challenge when developing microservices. In this article, we will explore how t...
  • Spring Boot with Okta and OPA
    Authentication (AuthN) and Authorization (AuthZ) is a common challenge when developing microservices. In this article, we will explore how t...
  • Getting started with Kafka in Python
    This article will provide an overview of Kafka and how to get started with Kafka in Python with a simple example. What is Kafka? ...
  • Getting started in GraphQL with Spring Boot
    In this article we will explore basic concepts on GraphQL and look at how to develop a microservice in Spring Boot with GraphQL support. ...

Copyright © StackStalk