Skip to content

Commit fdd86b2

Browse files
authored
Merge pull request #16 from urboob21/dev_branch
id 1763525961
2 parents 46335f3 + a49d9fc commit fdd86b2

File tree

4 files changed

+178
-0
lines changed

4 files changed

+178
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ set(APP_SOURCES
9999
"src/patterns/structural/Facade.cpp"
100100
"src/patterns/structural/Decorator.cpp"
101101
"src/patterns/behavioral/ChainOfCommand.cpp"
102+
"src/patterns/behavioral/Command.cpp"
102103
)
103104

104105
# Test files

docs/uml/patterns_behavioral_command.drawio.svg

Lines changed: 4 additions & 0 deletions
Loading

src/patterns/behavioral/ChainOfCommand.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ namespace
1616
{
1717
namespace CoR
1818
{
19+
/*
20+
* Handler - defines an interface for handling requests
21+
*/
1922
class IHandler
2023
{
2124
public:
@@ -57,6 +60,10 @@ namespace
5760
}
5861
};
5962

63+
/**
64+
* CoreteHandlers - handles the requests it is responsible for
65+
* If it can handle the request it does so, otherwise it sends the request to its successor
66+
*/
6067
class ConcreteHandlerGET : public AbstractHandler
6168
{
6269
private:
@@ -116,6 +123,9 @@ namespace
116123
}
117124
};
118125

126+
/**
127+
* Client - sends commands to the first object in the chain that may handle the command
128+
*/
119129
namespace Client
120130
{
121131
void clientCode(IHandler &handler, const std::string &request)
@@ -155,6 +165,7 @@ struct CoRAutoRunner
155165
{
156166
CoRAutoRunner()
157167
{
168+
std::cout << "\n--- CoR Pattern Example ---\n";
158169
CoR::run();
159170
}
160171
};
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Command is a behavioral design pattern that turns a request into a stand-alone object that contains all information about the request. (receivers, payloads)
2+
// This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.
3+
// Allows an object to send a command without knowing what object will receive and handle it.
4+
// Appicability:
5+
// (*) when you want to parameterize objects with operations.
6+
// (**) when you want to queue operations, schedule their execution, or execute them remotely.
7+
// (***) when you want to implement reversible operations.
8+
9+
// UML: docs/uml/patterns_behavioral_command.drawio.svg
10+
11+
#include <iostream>
12+
#include <string>
13+
14+
namespace
15+
{
16+
namespace Command
17+
{
18+
19+
/**
20+
* The Command interface usually declares just a single method for executing the command.
21+
* e.g. Save, Undo, Jump, Backup, CreateOrder
22+
*/
23+
class ICommand
24+
{
25+
public:
26+
virtual void execute() const = 0;
27+
};
28+
29+
/**
30+
* The Receiver class contains some business logic. Almost any object may act as a receiver.
31+
* Most commands only handle the details of how a request is passed to the receiver, while the receiver itself does the actual work.
32+
* e.g. Document, GameCharacter, DB service
33+
*/
34+
class Receiver
35+
{
36+
public:
37+
static void doCheck()
38+
{
39+
std::cout << "Receiver checking... \n";
40+
};
41+
static void doInit()
42+
{
43+
std::cout << "Receiver initializing... \n";
44+
};
45+
static void doLaunch(const std::string &arg)
46+
{
47+
std::cout << "Receiver launching... \n\t" << arg << "\n";
48+
};
49+
};
50+
51+
/**
52+
* Concrete Commands implement various kinds of requests.
53+
* A concrete command isn’t supposed to perform the work on its own, but rather to pass the call to one of the business logic objects.
54+
* However, for the sake of simplifying the code, these classes can be merged.
55+
*/
56+
class SimpleConcreteCommand : public ICommand
57+
{
58+
public:
59+
void execute() const override
60+
{
61+
std::cout << "\t SimpleCommand executed \n";
62+
}
63+
};
64+
65+
class ComplexConcreteCommand : public ICommand
66+
{
67+
private:
68+
Receiver *m_receiver;
69+
std::string m_payload;
70+
71+
public:
72+
ComplexConcreteCommand(Receiver *receiver, const std::string &payload) : m_receiver{receiver}, m_payload{payload} {};
73+
74+
void execute() const override
75+
{
76+
std::cout << "\t ComplexCommand executed \n";
77+
this->m_receiver->doCheck();
78+
this->m_receiver->doInit();
79+
this->m_receiver->doLaunch(m_payload);
80+
}
81+
};
82+
83+
/**
84+
*The Sender class (aka invoker) is responsible for initiating requests.
85+
*This class must have a field for storing a reference to a command object.
86+
*The sender triggers that command instead of sending the request directly to the receiver.
87+
*Note that the sender isn’t responsible for creating the command object. Usually, it gets a pre-created command from the client via the constructor.
88+
*e.g. Button, Shortcut, Scheduler, Event bus...
89+
*/
90+
class Invoker
91+
{
92+
private:
93+
ICommand *m_on_start;
94+
ICommand *m_on_finish;
95+
96+
public:
97+
explicit Invoker(ICommand *s = nullptr, ICommand *f = nullptr) : m_on_start{s}, m_on_finish{s}
98+
{
99+
}
100+
101+
~Invoker()
102+
{
103+
delete m_on_start;
104+
delete m_on_finish;
105+
}
106+
107+
void setOnStart(ICommand *command)
108+
{
109+
this->m_on_start = command;
110+
}
111+
112+
void setOnFinish(ICommand *command)
113+
{
114+
this->m_on_finish = command;
115+
}
116+
117+
void invoke() const
118+
{
119+
if (m_on_start != nullptr)
120+
{
121+
m_on_start->execute();
122+
}
123+
124+
if (m_on_finish != nullptr)
125+
{
126+
m_on_finish->execute();
127+
}
128+
}
129+
};
130+
131+
namespace Client
132+
{
133+
void clientCode(const Invoker *invoker)
134+
{
135+
invoker->invoke();
136+
}
137+
138+
}
139+
140+
void run()
141+
{
142+
Receiver *ui = new Receiver();
143+
// How to execute these command when something triggered
144+
Invoker *invoker = new Invoker();
145+
invoker->setOnStart(new SimpleConcreteCommand());
146+
invoker->setOnFinish(new ComplexConcreteCommand(ui, "cmd --version"));
147+
Client::clientCode(invoker);
148+
delete ui;
149+
}
150+
}
151+
}
152+
153+
struct CommandAutoRunner
154+
{
155+
CommandAutoRunner()
156+
{
157+
std::cout << "\n--- Command Pattern Example ---\n";
158+
Command::run();
159+
}
160+
};
161+
162+
static CommandAutoRunner instance;

0 commit comments

Comments
 (0)