Tuesday, January 16, 2024

Chain Of Responsibility Design Pattern using C++

Alright, imagine for a moment that you have a series of people in a room. Each person is trying to avoid doing a specific task, so they keep passing it on to the next person saying, "Not my job!". That's essentially the Chain of Responsibility pattern! The idea is to decouple the sender from the receiver by allowing multiple objects to handle the request.

Let's look at a C++ example where different members of a household are trying to avoid doing the dishes:

DishWasher.h
#ifndef _DISHWASHER_H_
#define _DISHWASHER_H_

#include <iostream>
#include <memory>

class DishWasher {
public:
    virtual ~DishWasher() = default;
    void setNext(std::shared_ptr<DishWasher> nextWasher) { this->nextWasher = nextWasher; }
    virtual void washDishes(const std::string& dishType) = 0;

protected:
    std::shared_ptr<DishWasher> nextWasher;
};

#endif
Teenager.h
#ifndef _TEENAGER_H_
#define _TEENAGER_H_

#include "DishWasher.h"

class Teenager : public DishWasher {
public:
    void washDishes(const std::string& dishType) override {
        if (dishType == "Plate") {
            std::cout << "Teenager: Fine! I'll wash the plate.\n";
        } else {
            std::cout << "Teenager: Not my job! Passing it on...\n";
            if (nextWasher) nextWasher->washDishes(dishType);
        }
    }
};

#endif
Parent.h
#ifndef _PARENT_H_
#define _PARENT_H_

#include "DishWasher.h"

class Parent : public DishWasher {
public:
    void washDishes(const std::string& dishType) override {
        if (dishType == "Pot") {
            std::cout << "Parent: Alright, I'll wash the pot.\n";
        } else {
            std::cout << "Parent: Not my responsibility! Passing it on...\n";
            if (nextWasher) nextWasher->washDishes(dishType);
        }
    }
};

#endif
Robot.h
#ifndef _ROBOT_H_
#define _ROBOT_H_

#include "DishWasher.h"

class Robot : public DishWasher {
public:
    void washDishes(const std::string& dishType) override {
        std::cout << "Robot: Fine humans, I'll wash the " << dishType << ".\n";
    }
};

#endif

main.cpp
#include "Teenager.h"
#include "Parent.h"
#include "Robot.h"

int main() {
    auto teen = std::make_shared<Teenager>();
    auto parent = std::make_shared<Parent>();
    auto robot = std::make_shared<Robot>();

    teen->setNext(parent);
    parent->setNext(robot);

    std::cout << "Attempting to wash a Plate:\n";
    teen->washDishes("Plate");

    std::cout << "\nAttempting to wash a Glass:\n";
    teen->washDishes("Glass");

    return 0;
}

In this funny example, when you try to wash a plate, the teenager reluctantly agrees. But if it's anything else, they pass it on. The parent only washes pots, and if it's anything else, they pass it on. The robot, being the last in the chain (and the most responsible one), washes anything that reaches it! 😂

No comments:

The Strategy Design Pattern a Behavioral Pattern using C++

The Strategy Design Pattern is a behavioral design pattern that enables selecting an algorithm's implementation at runtime. Instead of i...