Skip to content

Commit 93e1ecd

Browse files
committed
Add CoR pattern
1 parent 33ccdaf commit 93e1ecd

3 files changed

Lines changed: 167 additions & 0 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ set(APP_SOURCES
9898
"src/patterns/structural/Flyweight.cpp"
9999
"src/patterns/structural/Facade.cpp"
100100
"src/patterns/structural/Decorator.cpp"
101+
"src/patterns/behavioral/ChainOfCommand.cpp"
101102
)
102103

103104
# Test files

docs/uml/patterns_behavioral_CoR.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
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 << "\tNo 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 << "\tHandle 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 << "\tHandle 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 << "\tHandle 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

Comments
 (0)