Hi dear reader! As my PhD defense day had passed, I have a lot more time than some weeks ago, so I will be posting more often. Maybe not all the posts will be much interesting, or interesting for many people, but still they will be useful for some. This time I'm going to write about Command pattern implementation, the most simple, indeed.
As a little foreword, I want to say that most of the design patterns are very acceptable in terms of logic, many people are using them every day, but they are not aware that this small techniques or ideas are called patterns and have their specific names. The basic idea behind many patterns is decoupling the components of the system, or just the interacting/communicating objects. So that it is easy to replace them separately, to add new features, to make available dynamic (run-time) decision-making, to avoid compiling the whole code after a small change, etc.
So command pattern is meant for decoupling the command as a separate executable from the object it is bound to, i.e. treating the command as an object per se, not as an action. The most common examples of this are menus and toolbars, where each item executes a command, and this command is just a separate object bound to item. Besides the decoupling there is one more big plus in this approach - one can bind the command to as many items as wanted (this reminds about flyweight pattern but its another topic). So let's go ahead and start looking into details.
What we should have to look into details is:
- a command - the action to be executed
- an invoker - this can be anything starting from a button, a menu or toolbar item up to some callback manager, or a thread pool.
- a receiver - this should be the object the command acts upon
It's obvious that we need three different objects, thus, three different classes for the above list to exist. As far we have an only requirement from the command : it should be executable. Unless we know how it should be executed, or what it should do we can provide just an interface with a single pure virtual function:
class Command
{
public:
virtual void
Execute() = 0;
};
The receiver should be able to do something, so that the command can act upon it. So let's take a simple class with single method doing something.
class Receiver
{
public:
void Action()
{
std::cout
<< "Command received"
<< std::endl;
// don't forget to include <iostream> header
}
};
Now we need an invoker to invoke the command. It should know which command to invoke, so should somehow keep a reference to the command. The key point here is that the invoker should not care about how the command will execute, what it should act upon, and what it should do at all. So it uses the provided interface above and just calls the Execute() function as seen below.
class Invoker
{
Command
*m_command;
public:
Invoker(Command
*cmd = 0) : m_command(cmd)
{
}
void SetCommad(Command *cmd)
{
m_command
= cmd;
}
void Invoke()
{
if (0 != m_command)
{
m_command->Execute();
}
}
};
Note the SetCommand() function which lets to bind another command to the Invoker at run-time, so we are free to decide which command should be invoked by the current invoker.
What else do we need to test the system? A command. Actually we have provided an interface, but we don't have a concrete type to instantiate. So we need a concrete command with Execute() function body defined. Here we go:
class MyCommand : public
Command
{
Receiver
*m_receiver;
public:
MyCommand(Receiver
*rcv = 0) : m_receiver(rcv)
{
}
void SetReceiver(Receiver *rcv)
{
m_receiver
= rcv;
}
virtual void
Execute()
{
if (0 != m_receiver)
{
m_receiver->Action();
}
}
};
Let's look what we have in MyCommand. The implementation of Execute() method, which is a simple call to Receiver's Action(). Thus we decoupled the command from the real action it does under hood, binding a receiver to a command. The SetReceiver() function makes it easy to bind another receiver to the command. Actually this would be more meaningful if we had an abstract receiver class (interface with single Action() method) and then derived concrete receivers, which would act to the same command in an intrinsic way, but this does not change the essence.
So now we can test our command.
int main()
{
Receiver
r;
MyCommand
cmd(&r);
Invoker
caller(&cmd);
caller.Invoke();
return 0;
}
As we expected the command has been invoked. We've reached our goal. So what we get ? We get a freedom to change/remove the command of the invoker, we can change the receiver, all this at run-time. Now about compilation, if we have our interfaces in one module and we create some new commands in another, we don't need to rebuild the first one to use the new commands. Feel free to improvise on this scheme. This is all for this time, thank you for your time and interest.
Thank you for the article.
ReplyDeleteThe article is good man... thanks
ReplyDeletenice article thanks a lot!!
ReplyDeleteSimple and helpful!Thank you armenian bro :)
ReplyDeleteDear Arsel, I have multiple commands to process at run time according to my logice. How can I extend your implementation for this. Could you please help me in this?
ReplyDeleteRegards,
Can you please give more details?
DeleteThanks for your reply. I am thinking of using this design pattern for different error types (commands) in my application. I have ErrorStructure inside my class. This error structure contains different error parameters of int or std::string type. I need to fill it according to different error type from my application. The user of my class would receive the ErrorStructure from the method.
DeleteI C domain, I implement this behaviour by definging callback function and user would register/set these callbacks in his/her application. For the errortype, I would execute the respective function and filled ErrorStructure is returned to the user of my application.
Implemeting callback function from C to C++ brought me to your tutorial.
Do you need more details
So your question is how to run a C function from C++ ? I still do not understand well.
DeleteHow to implement the C callback mechanism in C++, would be my question. As mentioned in my previous reply, I need to implement a notification mechanism.
DeleteRegards,
While searching for a solution, I thought to implement this feedback mechanism using command/observer pattern.
DeleteCallback and command are different notions. Command is an object encapsulating an action and having all the required parameters to execute that action (method, object to call the method on, etc). Thus, you can share the same base Command interface among a lot of different commands and use them in a generic(OO) code. Also, this approach provides run-time binding, so that you can invoke the same command on any object, or make the target of the command any object (implementing a defined interface). That is what the command is meant for. Callback, on the other hand, is more a way to post-process some results of an action by or on another object. So for example, imagine you have a function which is doing some long arithmetic calculations, and when it finishes, it has some useful data that other parties are interested in. So this arithmetic calculator object can have a function for others to register their callbacks to get called with that useful data every time it is calculated.
Deletevoid registerCallback(std::function);
and then inside the real calculation code you have
// .... lots of calculation stuff
int result = // .. finally got the result;
// and then executing callbacks of all interested parties
for (auto f: callbacks) { f(result); }
}
You can ask why not return the result directly. Usually the interested parties are other components and they cannot directly know when the calculation started or finished, so even if you store the returned value, you will need some notification to let everyone know that a fresh result is ready for consumption. So in some sense the callback can be compared to event, but again the idea is not completely the same.
Just google "C++ callbacks" and you will find a lot of materials. Hope this helps.
This comment has been removed by the author.
ReplyDelete