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