1+ // CoR is a behavioral design pattern that lets you pass requests along a chain of handlers.
2+ // Upon receiving a request, each handler decides either to process the request
3+ // or to pass it to the next handler in the chain.
4+ // Allows an object to send a command without knowing what object will receive and handle it.
5+ // Appicability:
6+ // (*) when it’s essential to execute several handlers in a particular order.
7+ // (**)when the set of handlers and their order are supposed to change at runtime.
8+
9+ // UML: docs/uml/patterns_behavioral_CoR.drawio.svg
10+
11+ #include < iostream>
12+ #include < string>
13+ #include < vector>
14+
15+ namespace
16+ {
17+ namespace CoR
18+ {
19+ class IHandler
20+ {
21+ public:
22+ virtual void setNextHandler (IHandler *handler) = 0;
23+ virtual IHandler *setNext (IHandler *handler) = 0;
24+ virtual void handle (const std::string &request) = 0;
25+ };
26+
27+ class AbstractHandler : public IHandler
28+ {
29+ private:
30+ IHandler *m_setNext;
31+
32+ public:
33+ AbstractHandler () : m_setNext{nullptr } {};
34+
35+ void setNextHandler (IHandler *handler) override
36+ {
37+ this ->m_setNext = handler;
38+ }
39+
40+ // handler1->setNext(handler2)->setNext(handler3)
41+ IHandler *setNext (IHandler *handler) override
42+ {
43+ this ->m_setNext = handler;
44+ return handler;
45+ }
46+
47+ void handle (const std::string &request) override
48+ {
49+ if (this ->m_setNext != nullptr )
50+ {
51+ this ->m_setNext ->handle (request);
52+ }
53+ else
54+ {
55+ std::cout << " \t No handler processed request: " << request << " \n " ;
56+ }
57+ }
58+ };
59+
60+ class ConcreteHandlerGET : public AbstractHandler
61+ {
62+ private:
63+ static constexpr const char *header = " GET" ;
64+
65+ public:
66+ void handle (const std::string &request) override
67+ {
68+ if (request.rfind (header, 0 ) == 0 )
69+ {
70+ // If request is eligible, handle it
71+ std::cout << " \t Handle GET request: " << request << " \n " ;
72+ // In realworld, it should be other logics here
73+ }
74+ else
75+ {
76+ AbstractHandler::handle (request);
77+ }
78+ }
79+ };
80+
81+ class ConcreteHandlerPUT : public AbstractHandler
82+ {
83+ private:
84+ static constexpr const char *header = " PUT" ;
85+
86+ public:
87+ void handle (const std::string &request) override
88+ {
89+ if (request.rfind (header, 0 ) == 0 )
90+ {
91+ std::cout << " \t Handle PUT request: " << request << " \n " ;
92+ }
93+ else
94+ {
95+ AbstractHandler::handle (request);
96+ }
97+ }
98+ };
99+
100+ class ConcreteHandlerPOST : public AbstractHandler
101+ {
102+ private:
103+ static constexpr const char *header = " POST" ;
104+
105+ public:
106+ void handle (const std::string &request) override
107+ {
108+ if (request.rfind (header, 0 ) == 0 )
109+ {
110+ std::cout << " \t Handle POST request: " << request << " \n " ;
111+ }
112+ else
113+ {
114+ AbstractHandler::handle (request);
115+ }
116+ }
117+ };
118+
119+ namespace Client
120+ {
121+ void clientCode (IHandler &handler, const std::string &request)
122+ {
123+ handler.handle (request);
124+ }
125+ }
126+
127+ void run ()
128+ {
129+ // Setup Chain of Responsibility
130+ IHandler *postHandler = new ConcreteHandlerPOST ();
131+ IHandler *gettHandler = new ConcreteHandlerGET ();
132+ IHandler *puttHandler = new ConcreteHandlerPUT ();
133+ postHandler->setNext (gettHandler)->setNext (puttHandler);
134+
135+ // Send requests to the chain
136+ std::string dummy = " DUMMY .." ;
137+ std::string postRequest = " POST /test/demo_form.php HTTP/1.1 .." ;
138+ std::string getRequest = " GET /users/123 .." ;
139+ std::cout << " Send dummy request\n " ;
140+ Client::clientCode (*postHandler, dummy);
141+ std::cout << " Send POST request\n " ;
142+ Client::clientCode (*postHandler, postRequest);
143+ std::cout << " Send GET request\n " ;
144+ Client::clientCode (*postHandler, getRequest);
145+
146+ delete postHandler;
147+ delete gettHandler;
148+ delete puttHandler;
149+ }
150+ }
151+
152+ }
153+
154+ struct CoRAutoRunner
155+ {
156+ CoRAutoRunner ()
157+ {
158+ CoR::run ();
159+ }
160+ };
161+
162+ static CoRAutoRunner instance;
0 commit comments