Click here to Skip to main content
15,881,812 members
Articles / Programming Languages / C# 2.0

Understanding and Implementing Command Pattern in C#

Rate me:
Please Sign up or sign in to vote.
4.47/5 (26 votes)
2 Mar 2012CPOL4 min read 156.8K   1.6K   53   16
Understanding and Implementing Command Pattern in C#

Introduction

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

Background

There are many a times in our application that we want to perform multiple operations on same data. I mean the scenarios when the user has some data and he has an option of doing one out of many operations in that data. 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 had to place in my code. Now what I could do is to have my action invoker call the methods of action reciever/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 find myself changing the existing code very often.

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

Command Pattern talk about encapsulating all the requests coming from the invoker in Objects, pass then to the reciever and let the reciever take the 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.

Image 1

  • 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 corresponding operationon Receiver.
  • Client: creates a ConcreteCommand object and sets its receiver
  • Invoker: It will use Command object to carry out the request
  • Receiver: It contains the real operational logic that need to be performed on the data.

Using the code

Let us now see how to have a simple Command pattern implementation by writting a small Calculator sort of application. We will focus on understanding command pattern so we will operate on fix set os data and will try to perform basic oeprations on them. Lets say we will be creating an appliction like this

Image 2

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

So let us start by writting the Command class.

C#
abstract class ACommand
{
    protected IReciever reciever_ = null;

    public ACommand(IReciever reciever)
    {
        reciever_ = reciever;
    }

    public abstract int Execute();
}

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

C#
class AddCommand : ACommand
{
    public AddCommand(IReciever reciever)
        :base(reciever)
    {

    }
    public override int Execute()
    {
        reciever_.SetAction(ACTIO_LIST.ADD);
        return reciever_.GetResult();
    }
}

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

    }
    public override int Execute()
    {
        reciever_.SetAction(ACTIO_LIST.SUBTRACT);
        return reciever_.GetResult();
    }
}

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

    }
    public override int Execute()
    {
        reciever_.SetAction(ACTIO_LIST.MULTIPLY);
        return reciever_.GetResult();
    }
}

So now we have the command hierarchy for our application ready. Now let is work on writting the real application logic. We will be needing a class that will do the calculations i.e. The Reciever. lets have an interface to represent the major functionalities of the reciever.

C#
//This is a helper type created to decide inside reciever
enum ACTIO_LIST
{        
    ADD,
    SUBTRACT,
    MULTIPLY
}

interface IReciever
{
    void SetAction(ACTIO_LIST action);
    int GetResult();
}

and the concrete Implementation of the Reciever i.e. our Calculator class

C#
class Calculator :IReciever
{
    int x_;
    int y_;

    ACTIO_LIST currentAction;

    public Calculator(int x, int y)
    {
        x_ = x;
        y_ = y;
    }

    #region IReciever Members

    public void SetAction(ACTIO_LIST action)
    {
        currentAction = action;
    }

    public int GetResult()
    {
        int result;
        if (currentAction == ACTIO_LIST.ADD)
        {
            result = x_ + y_;

        }
        else if (currentAction == ACTIO_LIST.MULTIPLY)
        {
            result = x_ * y_;
        }
        else
        {
            result = x_ - y_;
        }
        return result;
    }

    #endregion
}

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

C#
public partial class testForm : Form
{
    IReciever calculator = null;
    ACommand command = null;
    AddCommand addCmd = null;
    SubtractCommand subCmd = null;
    MultiplyCommand mulCmd = null;

    public testForm()
    {
        InitializeComponent();
    }

    private void testForm_Load(object sender, EventArgs e)
    {
        calculator = new Calculator(20, 10);

        addCmd = new AddCommand(calculator);
        subCmd = new SubtractCommand(calculator);
        mulCmd = new MultiplyCommand(calculator);
    }

    private void radioAdd_CheckedChanged(object sender, EventArgs e)
    {
        if (radioAdd.Checked == true)
        {
            command = addCmd;
        }
        else if(radioSub.Checked == true)
        {
            command = subCmd;
        }
        else if (radioMultiply.Checked == true)
        {
            command = mulCmd;
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        label3.Text = "Result: " + command.Execute().ToString();
    }        
}

The event change of radio buttons are simply changing the command object to be used and whe the user chooses to get the result the appropiate command object will be used to fetch the result for him. Befor wrapping up lets try to look at the clas diagram of our code and map it with the Gofs diagram.

Image 3

Points of Interest

Command pattern is a very good way of decrease the coupling between sender and reciever. The most important thing to remember while implementing the command pattern is that the Command is just a link between sender and reciever. It should only tell the reciever what the sender is expecting. It should never alter the logic of sender and reciever in any way.

History

01 March 2012: Understanding and Implementing Command Pattern in C#

License

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


Written By
Architect
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.

  • Microsoft Certified Technology Specialist (MCTS): Web Applications Development with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Accessing Data with Microsoft .NET Framework 4
  • Microsoft Certified Technology Specialist (MCTS): Windows Communication Foundation Development with Microsoft .NET Framework 4

If you like my articles, please visit my website for more: www.rahulrajatsingh.com[^]

  • Microsoft MVP 2015

Comments and Discussions

 
Generalmy vote 5 Pin
maxoptimus13-May-20 5:52
maxoptimus13-May-20 5:52 
GeneralMy vote of 4 Pin
Ehsan yazdani rad12-Dec-16 2:47
Ehsan yazdani rad12-Dec-16 2:47 
QuestionReview Pin
Robert Amlotte17-Jul-15 6:27
Robert Amlotte17-Jul-15 6:27 
SuggestionMy vote of 4 Pin
GenadyT24-Mar-14 5:05
professionalGenadyT24-Mar-14 5:05 
QuestionReturning command acknowledgement from receiver to sender Pin
AfterBurn2711-Jan-14 3:50
AfterBurn2711-Jan-14 3:50 
AnswerRe: Returning command acknowledgement from receiver to sender Pin
Rahul Rajat Singh12-Jan-14 16:27
professionalRahul Rajat Singh12-Jan-14 16:27 
I think you might want to look at the observer pattern if you know which class is going to handle the acknowledgment. In case the acknowledgement handling depends on the type of acknowledgement then perhaps the chain of responsibility pattern will be useful.

You will have to one of these patterns with the command pattern.

One idea is to make the command itself observable so that the command sender can subscribe as acknowledgment receiver. and the module which is acting upon the command can invoke the acknowledgment sending process in the command. I am not sure how good a design this will be because I need to look at the complete design to come up with a perfect solution. But this will perhaps give you a starting point to implement the solution.
Twenty years from now you will be more disappointed by the things that you didn't do than by the ones you did do. So throw off the bowlines. Sail away from the safe harbor. Catch the trade winds in your sails. Explore, Dream. Discover.

QuestionIssue Pin
FatCatProgrammer24-Oct-13 8:46
FatCatProgrammer24-Oct-13 8:46 
Questionthanks Pin
zzfima18-Dec-12 18:46
zzfima18-Dec-12 18:46 
GeneralMy vote of 5 Pin
Shabbazz6-Mar-12 14:47
professionalShabbazz6-Mar-12 14:47 
GeneralMy vote of 4 Pin
danlobo5-Mar-12 1:24
danlobo5-Mar-12 1:24 
GeneralMy vote of 3 Pin
tigercont3-Mar-12 21:31
tigercont3-Mar-12 21:31 
GeneralRe: My vote of 3 Pin
John Brett4-Mar-12 21:44
John Brett4-Mar-12 21:44 
GeneralRe: My vote of 3 Pin
Rahul Rajat Singh5-Mar-12 0:09
professionalRahul Rajat Singh5-Mar-12 0:09 
GeneralRe: My vote of 3 Pin
John Brett5-Mar-12 0:26
John Brett5-Mar-12 0:26 
GeneralRe: My vote of 3 Pin
danlobo5-Mar-12 1:26
danlobo5-Mar-12 1:26 
GeneralRe: My vote of 3 Pin
tigercont5-Mar-12 0:37
tigercont5-Mar-12 0:37 

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

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