Click here to Skip to main content
Click here to Skip to main content

Understanding and Implementing the Command Pattern in C++

By , 9 Mar 2012
Rate this:
Please Sign up or sign in to vote.

Introduction

The idea of this article is to understand what is Command Pattern, when is it useful, and how can we get a basic implementation of Command Pattern using C++.

Background

There are many a times in our applications that we want to perform multiple operations on the same data. I mean scenarios when the user has some data and he has an option of doing one out of many operations on that data. An example could be an image processor: I could choose to rotate, flip and/or invert colors of the photo. Also I could find myself not happy with the action and I may want to undo my action. Now this is all business logic that I have to place in my code. Now what I could do is have my action invoker call the methods of the action receiver/taker and achieve this. But then I will have to write a lot of conditional code. I will have to write very similar code for each action. Also, If I have more commands, I will find myself changing the existing code very often.

Instead of taking the above approach, I could devise a mechanism where all my actions can somehow be handled polymorphically thus giving me a clean and less error prone code/design. This idea is the basic intent of writing a Command Pattern.

The Command Pattern talks about encapsulating all the requests coming from the invoker in objects, passing them to the receiver, and letting the receiver take actions. If I have many actions to perform, I can have a hierarchy of commands and handle them polymorphically.

GoF defines Command Pattern as "Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations." So let us look at the class diagram for the Command pattern and try to understand it.

  • Command: This is an interface for executing an action.
  • ConcreteCommand: This object specifies the binding between a Receiver/action taker and an action invoker. This object is responsible for executing the corresponding operation on the Receiver.
  • Client: Creates a ConcreteCommand object and sets its receiver.
  • Invoker: It will use the Command object to carry out the request.
  • Receiver: It contains the real operational logic that needs to be performed on the data.

Using the code

Let us now see how to have a simple Command pattern implementation by writing a small Calculator sort of application. We will focus on understanding the Command pattern so we will operate on a fixed set of data and will try to perform basic operations on them. Let's say we will be creating an application like this:

Note: The idea here is to understand the Command Pattern and not write a calculator. Also, this example is small so Command Pattern might seem an overkill for this.

So let us start by writing the Command class.

class ACommand
{
protected:

    IReciever *pReciever_;

public:

    ACommand(IReciever *reciever)
        :pReciever_(reciever)
    {
    }

    virtual int Execute() = 0;
};

This class is an abstract class and will be used as an interface for the execution of commands. Let us now write the ConcreteCommand classes that will inherit this abstract class.

#include "Acommand.h"

class AddCommand : public ACommand
{
public:
    AddCommand(IReciever *reciever)
        : ACommand(reciever)
    {

    }

    int Execute()
    {
        pReciever_->SetAction(TYPES::ACTION_LIST::ADD);
        return pReciever_->GetResult();
    }
};

class SubtractCommand : public ACommand
{
public:
    SubtractCommand(IReciever *reciever)
        : ACommand(reciever)
    {

    }

    int Execute()
    {
        pReciever_->SetAction(TYPES::ACTION_LIST::SUBTRACT);
        return pReciever_->GetResult();
    }
};

class MultiplyCommand : public ACommand
{
public:
    MultiplyCommand(IReciever *reciever)
        : ACommand(reciever)
    {

    }

    int Execute()
    {
        pReciever_->SetAction(TYPES::ACTION_LIST::MULTIPLY);
        return pReciever_->GetResult();
    }
};

We have the command hierarchy for our application ready. Now let us work on writing the real application logic. We will need a class that will do the calculations, i.e., the Reciever. Let us have an interface to represent the major functionalities of the receiver.

namespace TYPES
{
    enum ACTION_LIST
    {
        ADD,
        SUBTRACT,
        MULTIPLY
    };
};

class IReciever
{
public:
    virtual void SetAction(TYPES::ACTION_LIST action) = 0;
    virtual int GetResult() = 0;    
};

and the concrete implementation of the Reciever, i.e., our Calculator class

#include "IReciever.h"

class Calculator : public IReciever
{
    int x_;
    int y_;
    TYPES::ACTION_LIST currentAction;

public:

    Calculator(int x, int y)
        :x_(x), y_(y)
    {
    }

    void SetAction(TYPES::ACTION_LIST action)
    {
        currentAction = action;
    }

    int GetResult()
    {
        int result;
        if (currentAction == TYPES::ACTION_LIST::ADD)
        {
            result = x_ + y_;

        }
        else if (currentAction == TYPES::ACTION_LIST::MULTIPLY)
        {
            result = x_ * y_;
        }
        else
        {
            result = x_ - y_;
        }
        return result;
    }
};

We will also be needing a class that will let the user choose the command to execute, i.e., the Client (this will be the UI in our case). Finally, we will write an Invoker which will again be the user interface in our case.

//Dialogs header is the place to declate class level variables
private:    
Calculator calculator;   
ACommand *command; //This will be used to invoke commands

AddCommand addCmd;
SubtractCommand subCmd;
MultiplyCommand mulCmd;

//Create class members in member initialization list
CCommandTestCppDlg::CCommandTestCppDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CCommandTestCppDlg::IDD, pParent),
    calculator(30,20),
    command(0),
    addCmd(&calculator),
    subCmd(&calculator),
    mulCmd(&calculator)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

//Handle the selection change of radio and assign respective command object
void CCommandTestCppDlg::OnBnClickedRadio1()
{
    command = &addCmd;
}

void CCommandTestCppDlg::OnBnClickedRadio2()
{    
    command = &subCmd;
}

void CCommandTestCppDlg::OnBnClickedRadio3()
{
    command = &mulCmd;
}

//Do the calculation and show the result
void CCommandTestCppDlg::OnBnClickedButton1()
{
    CString str;
    int result = command->Execute();
    str.Format(_T("Result: %d"), result);
    SetDlgItemText(IDC_STATIC3, str);
}

The event change of radio buttons are simply changing the command object to be used, and when the user chooses to get the result, the appropriate command object will be used to fetch the result for him.

Points of interest

Command Pattern is a very good way of decreasing the coupling between the sender and receiver. The most important thing to remember while implementing the Command pattern is that the Command is just a link between the sender and receiver. It should only tell the receiver what the sender is expecting. It should never alter the logic of the sender and receiver in any way. I have a similar implementation of Command Pattern in C#. Please refer to that if you want to see the C# code and the subtle similarities and differences in code.

History

  • 03 March 2012: First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Rahul Rajat Singh
Software Developer (Senior)
India India
I Started my Programming career with C++. Later got a chance to develop Windows Form applications using C#. Currently using C#, ASP.NET & ASP.NET MVC to create Information Systems, e-commerce/e-governance Portals and Data driven websites.

My interests involves Programming, Website development and Learning/Teaching subjects related to Computer Science/Information Systems. IMO, C# is the best programming language and I love working with C# and other Microsoft Technologies.
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
QuestionMore case studies for Command pattern PinmemberMember 437847926-Dec-13 6:29 
QuestionJust a thought PinmemberMember 335693913-Mar-12 20:13 
QuestionWhy 2 equal articles? PinmemberNelek11-Mar-12 12:48 
AnswerRe: Why 2 equal articles? PinmemberRahul Rajat Singh11-Mar-12 16:31 
GeneralRe: Why 2 equal articles? PinmemberNelek13-Mar-12 8:30 
QuestionMessage Automatically Removed Pingroupkjlfdgehe9-Mar-12 15:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 9 Mar 2012
Article Copyright 2012 by Rahul Rajat Singh
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid