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

Command Design Pattern

By , 4 May 2011
 

You can see this and other great articles on Design Patterns here.

The Command Design Pattern allows you to store a list of actions that you can execute later. A common example is storing the undo actions in an application. The undo actions are stored as the user is making changes in an application. When the user decides to perform the undo, the undo actions are retrieved and executed.

The benefit of the Command Pattern is that it hides the details of the actions that needs to be performed, so that the client code does not need to be concerned about the details when it needs to execute the actions. The client code just needs to tell the application to execute the command that was stored.

In an undo example, if the user moved a rectangle from position X to position Y, then the undo action will be to move the rectangle from position Y back to position X. The details of this undo action are stored in the command objects so that when the user needs to execute the undo action, the application only needs to tell the command object to execute its action without knowing that it is supposed to move the rectangle from position Y back to position X.

The Command pattern is not focused so much on the sequence of the actions stored, but more on hiding the details of the action it needs to perform.

We will do an actual example of the Command Design Pattern to show you how it works. But for now, let’s look at the UML of the Command Design Pattern:

  • The ICommand interface defines the methods that all Command classes must implement.
  • The Command class stores the details of the actions that need to be performed (the location of position Y and position X for the undo).
  • The Receiver class performs the action when called upon (moving the rectangle from position Y back to position X).
  • The Invoker class stores the list of commands and can ask the ICommand to execute.
  • The Client class uses the Invoker to run the commands.

The client code (calling code) will used the Invoker to run the commands, where the Command objects will call the Receiver to perform the action. The benefit is that the client code does not need to know what is stored in the Command objects nor the actions that will be performed by the Receiver, and this is the key to the Command Design Pattern.

Now let’s do an example. In our example, we need to store some undo actions when the user is using the application, and when the user decides to perform the undo, we can just use the invoker to run the commands. Below is the UML for our undo example:

  • The UndoCommand class stores the location where the rectangle is supposed to move back.
  • The UndoPerformer will move the rectangle back to its original position, taking the UndoCommand as the parameter.
  • The Invoker stores the list of undo commands.

 

Below are the implementation code and the output of our example; notice that the client code does not need to know the details of the undo action when it needs to call it. The client code is simply:

invoker.RunCommand();
class Client
{
    static void Main(string[] args)
    {
        Invoker i = new Invoker();
        //save undo to position 100
        ICommand a = new UndoCommand(100);
        i.AddCommand(a);
        //save undo to position 200
        ICommand b = new UndoCommand(200);
        i.AddCommand(b);
        //perform the undo
        i.RunCommand();   //the client does not need to know about the details of the undo
    }
}

public interface ICommand
{
    void Execute();
}

public class UndoCommand : ICommand
{
    private int location;

    public int Location
    {
        get { return location; }
    }

    public UndoCommand(int originalLocation)
    {
        location = originalLocation;
    }

    public void Execute()
    {
        new UndoPerformer().Undo(this);
    }
}

public class Invoker
{
    private Stack<icommand> commandList = new Stack<icommand>();

    public void RunCommand()
    {
        while (commandList.Count > 0)
            commandList.Pop().Execute();
    }

    public void AddCommand(ICommand c)
    {
        commandList.Push(c);
    }
}

public class UndoPerformer
{
    public void Undo(ICommand c)
    {
        if (c is UndoCommand)
        {
            int originalLocation = (c as UndoCommand).Location;
            Console.WriteLine("Moving back to position: " + originalLocation);
        }
    }
}

Liked this article? You can see this and other great articles on Design Patterns here.

License

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

About the Author

DevLake
United States United States
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 3memberLivio Francescucci4 May '13 - 21:16 
The code is clear and simple enough, but the example with this implementation of Undo doesn't fit completely with it. The "Undo" is in fact more often used with Memento pattern. I would suggest you to provide a different example.
GeneralMy vote of 5memberMC19727 Dec '11 - 4:21 
Cool
GeneralMy vote of 1memberBill SerGio, Infomercial King4 May '11 - 8:13 
This is a tip and not an article. All I see is a lot of spam from this author like he copying out of a book or something.
GeneralRe: My vote of 1memberDaveAuld4 May '11 - 8:46 
These are neither Article or Tip.
 
The author has linked a technical blog (look at the top of the item). This used to be shown in a separate tab on the home page, and several members have requested this be re-instated.
Dave
Find Me On: Web|Facebook|Twitter|LinkedIn

Folding Stats: Team CodeProject

GeneralRe: My vote of 1memberBill SerGio, Infomercial King4 May '11 - 8:59 
I appreciated your pointing out it is a tip BUT it appears under articles on the main page and if I set the filter on CodeProject to articles all I can see are these posts from this author. Also what he is posting is not new and he siggests that UML is te way to model these designs--UML is a waste of time in my opinion and the "models" he alludes to are all independ of any modelling tools. Maybe CodepProject should fix their filter to show his stuff under tips and not under the articles filter.
http://www.GeminiGroupTV.com

GeneralRe: My vote of 1memberDaveAuld4 May '11 - 9:03 
Bill SerGio, Infomercial King wrote:
appreciated your pointing out it is a tip

I didn't, i said it is a blog Smile | :)
 
Anyway, if the filters are broken or you think there is an improvement to be made, then raise it in the site bugs and suggestions forum.
 
As for the content of these, i haven't really bothered to look at them, the only reason i came to this one was i clicked it at random to do a compare of the revisions to see what had changed from his last batch of updates he did a few days ago. (to see if there was any really).
Dave
Find Me On: Web|Facebook|Twitter|LinkedIn

Folding Stats: Team CodeProject

GeneralMy vote of 4memberAre Jay25 Apr '11 - 14:53 
simple to understand and with a simple code sample that exposes the functionally of the article.
GeneralNice ArticlememberAre Jay25 Apr '11 - 14:51 
Thanks for the design pattern series.
 
I am looking of a pattern that has an implemention like the command pattern but the Execute() needs to handle:
- void
- String
- XmlDocument
- XDocument
- int
- bool
- etc...
 
Any helpful tips?
I'm listening but I only speak GEEK.

GeneralRe: Nice ArticlememberJV999926 Apr '11 - 20:52 
With this less info it's hard for everybody to give you an answer. However I'm pretty sure there is not a single pattern you can use, but most likely you will have to combine multiple to achieve your goal. Eg the Mediator with the Command-pattern might fit your needs.
GeneralRe: Nice ArticlememberAre Jay27 Apr '11 - 6:31 
Thank you for the help, I will look at combining the two patterns.
 
Details:
I am using MEF to loosely couple my API so I can extend the business logic of the API (a plug and play feel).
So, the API is the host and it using the ExportMetadata Attributes of the Module (plugin, extension, etc.) to determine how to the module is to be treated.
Examples of ExportMetadata Attributes:
- Pre
- Post
- InsteadOf
- Default
** an Aspect Orientated approach to implementing the Modules.
 
So, the API is using a series of Controller objects to determine how the 'extended' Module should behave within the API...
 
Now to the original meaning of my initial question...
 
these controllers are passing around the Lazy<T, TMetadata> object imported to determine it's behavior
public class GenericController<T>
{
        private bool _isDefault = false;
	private IEnumerable<Lazy<T, IExtensionMetadata>> _imports { get; set; }	
		
	public Lazy<T, IExtensionMetadata> Execute { get; private set; }
	public IEnumerable<Lazy<T, IExtensionMetadata>> PreExecute { get; private set; }
	public IEnumerable<Lazy<T, IExtensionMetadata>> PostExecute { get; private set; }
 
	public GenericController(IEnumerable<Lazy<T, IExtensionMetadata>> imports, bool defaultOnly) : this( imports )
	{ this._isDefault = defaultOnly; }
 
	public GenericController(IEnumerable<Lazy<T, IExtensionMetadata>> imports)
	{ this._imports = imports; this.Init(); }
 
	void Init()
	{
		// process business rules of modules
	}
}
 
So when implementing the GenericConroller
...
String result = String.Empty;
GenericController<ArchivableDocument_Add> controller =
	new GenericController<ArchivableDocument_Add>(this._add);
foreach (var pre in controller.PreExecute)
	pre.Value.Add(userName, objectType, objectId, caption, url, messageId, taskId);
 
result = controller.Execute.Value.Add(userName, objectType, objectId, caption, url, messageId, taskId);
 
foreach (var post in controller.PostExecute)
	post.Value.Add(userName, objectType, objectId, caption, url, messageId, taskId);
 
return result;
...
 
Execution happens outside the contoller because:
- I may or may not have a return type
- Executing method signatures will alway be different
Ideally I'd like it to be as follows:
...
GenericController<ArchivableDocument_Add> controller =
	new GenericController<ArchivableDocument_Add>(this._add);
 
controller.Execute();
 
return conroller.Result as String;
...
 
Thoughts?
I'm listening but I only speak GEEK.

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 4 May 2011
Article Copyright 2011 by DevLake
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid