-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChainOfCommand.cpp
More file actions
149 lines (127 loc) · 4.24 KB
/
ChainOfCommand.cpp
File metadata and controls
149 lines (127 loc) · 4.24 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
// 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 ~IHandler() = default;
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);
}
} // namespace Client
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;
}
} // namespace CoR
} // namespace
#include "ExampleRegistry.h"
class ChainOfResponsibilityExample : public IExample {
public:
std::string group() const override { return "patterns/behavioral"; }
std::string name() const override { return "ChainOfResponsibility"; }
std::string description() const override { return "CoR Pattern Example"; }
void execute() override { CoR::run(); }
};
REGISTER_EXAMPLE(ChainOfResponsibilityExample, "patterns/behavioral",
"ChainOfResponsibility");