Chain of responsibility pattern
1. Usage
- Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it. [GoF, p223]
- Launch-and-leave requests with a single processing pipeline that contains many possible handlers.
- An object-oriented linked list with recursive traversal.
2. UML class diagram



3. Pros
- Decouples the sender of the request and its receivers.
- Simplifies your object as it doesn’t have to know about the chain structure and keep direct references to its members.
- Allows you to add or remove responsibilities dynamically by changing the members or order of the chain.
4. Cons
- Hard to observe the run-time characteristics and debug
5. Source code
// From http://cpp-reference.ru/patterns/behavioral-patterns/chain-of-responsibility/
#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
class Base
{
// 1. Указатель "next" в базовом классе
Base *next;
public:
Base()
{
next = 0;
}
void setNext(Base *n)
{
next = n;
}
void add(Base *n)
{
if (next)
next->add(n);
else
next = n;
}
// 2. Метод базового класса, делегирующий запрос next-объекту
virtual void handle(int i)
{
next->handle(i);
}
};
class Handler1: public Base
{
public:
/*virtual*/void handle(int i)
{
if (rand() % 3)
{
// 3. 3 из 4 запросов не обрабатываем
cout << "H1 passsed " << i << " ";
// 3. и делегируем базовому классу
Base::handle(i); }
else
cout << "H1 handled " << i << " ";
}
};
class Handler2: public Base
{
public:
/*virtual*/void handle(int i)
{
if (rand() % 3)
{
cout << "H2 passsed " << i << " ";
Base::handle(i);
}
else
cout << "H2 handled " << i << " ";
}
};
class Handler3: public Base
{
public:
/*virtual*/void handle(int i)
{
if (rand() % 3)
{
cout << "H3 passsed " << i << " ";
Base::handle(i);
}
else
cout << "H3 handled " << i << " ";
}
};
int main()
{
srand(time(0));
Handler1 root;
Handler2 two;
Handler3 thr;
root.add(&two);
root.add(&thr);
thr.setNext(&root);
for (int i = 1; i < 10; i++)
{
root.handle(i);
cout << \n;
}
}