David Redding

Blog? What blog? Theres no blog to see here. Please move along
posts - 56, comments - 104, trackbacks - 28

My Links

News

www.flickr.com
This is a Flickr badge showing public photos from dredding. Make your own badge here.

Twitter












Tag Cloud

Article Categories

Archives

Post Categories

.Net Resource Sites

.Net User Group Sites

Language Resource Sites

Mason Sites

My Bloggin' Buddies

My take on the command pattern.

   Ok, so, what started this whole "I gotta blog now!" thing was a short interview I did with Josh Holmes on how I implemented the command pattern to give myself a flexible Undo / Redo.  What I did was simple, which probably also means, it could be better.

                  In short, in the Command Pattern you have three players.  The Receiver (The guy who actually has real code to execute), The Invoker (The guy who normally calls the receiver to do something) and the Command (think of the command as a proxy... I’ll explain).

                Ok, so say I’m writing a simple app that moves a robot every time the user clicks a specific button.  The code would be something like this.

public class MyForm : Form

{

    private void Button1_click(object sender, EventArgs e)

    {

        MoveRobotForward();

    }

    private void Button2_click(object sender, EventArgs e)

    {

        MoveRobotBackward();

    }

 

    public void MoveRobotForward()

    {

        //move him forward

    }

    public void MoveRobotBackward()

    {

        //Move him backward

    }

}

                So what happens when I want to undo this command, or for that matter, I want to undo a whole bunch of movements in sequence?  I could store each movement in a collection right?  Maybe even remove it from the collection, or something along those lines?  That’s essentiatally what the command pattern is.

                 The basics of the pattern are to create an object out of a function call, then you store that object in a collection (typically in the invoker). Once it's stored in the collection, you can re-call it and execute it, or undo it, so on and so forth.

   Let’s start with the Command class:

public abstract class Command

{

    protected MyForm m_receiver;

    public Command(MyForm in_receiver)

    {

        m_receiver = in_receiver;

    }

 

    public abstract void Execute();

    public abstract void UnDo();

}

Ok, this is our “Base” command.  Notice it has a refrence to our form, and requires a Execute and Undo method.  They're abstract so no code yet.

Next up, our Invoker class.  This is where the meat of the Undo/Redo lives.

public class Invoker

{

    List<Command> commands;

    static Invoker m_invoker;

    static int m_location = 0;

 

    private Invoker()

    {

        commands = new List<SequenceUCCommand>();

    }

    public static Invoker Instance()

    {

        if (m_invoker == null)

            m_invoker = new Invoker();

        return m_invoker;

    }

 

    public void ExecuteCommand(Command in_command)

    {     

      if (in_command != null)

            {

                if (m_location < commands.Count)

                {

                    int i = m_location;

                    while (i < commands.Count)

                    {

                        commands.RemoveAt(0);

                    }

                }

                commands.Add(in_command);

                m_location++;

                in_command.Execute();

 

            }

 

           

    }

 

 

        public void Undo(int in_undoLevels)

        {

            for (int i = 0; i < in_undoLevels; i++)

            {

                if(m_location>0)

                    commands[--m_location].Undo();

            }

        }

        public void Redo(int in_redoLevels)

        {

            for (int i = 0; i < in_redoLevels; i++)

            {

                if (m_location < commands.Count)

                    commands[m_location++].Execute();

            }

        }

    }

 

Lots of code kind of.  It’s real simple though.  Let me explain before you walk away.  The invoker will “Execute” a command on my behalf.  Thanks to the wonders of Polymorphism, so long as the command inherits from “Command” were good.  As we just saw, each command has to have Execute and Undo.  This is where the ExecuteCommand, and Undo and Redo methods come in.  Execute command will execute the method and add it to the collection. It’s also checking to see if there have been any commands undone before adding this command, and removes them.  I’ll explain that one later. Undo/Redo, both increment/decrement the location in the collection we want to execute from (IE which command should I look at to execute).

Simple right?

Now here is the actual command, hopefully this will help make things make sense

public class MoveRobot:Command

{

    private int m_forward;

    public MoveRobot(MyForm in_reciver, bool in_forward):base(in_reciver)

    {

        m_direction = in_direction;

    }

 

    public override void Execute()

    {

        //Check direction

        if (m_forward)

            m_receiver.MoveRobotForward();

        else

            m_receiver.MoveRobotBackward();

    }

 

    public override void UnDo()

    {

        //check direction

        if (m_forward)

            m_receiver.MoveRobotBackward();

        else

            m_receiver.MoveRobotForward();

    }

}

 

Ah Ha!! So… this command is responsible for actually calling the code on the form to “Do” something.

So we just modify our form to use the invoker..

 

public class MyForm : Form

{

    private Invoker m_invoker = Invoker.Instance();

 

   

    private void Button1_click(object sender, EventArgs e)

    {

        //MoveRobotForward(); instead of calling directly...

        MoveRobot mr = new MoveRobot(this, true);

        m_invoker.ExecuteCommand(mr);

    }

    private void Button2_click(object sender, EventArgs e)

    {

        MoveRobot mr = new MoveRobot(this, false);

        m_invoker.ExecuteCommand(mr);

    }

 

 

    public void MoveRobotForward()

    {

        //move him forward

    }

    public void MoveRobotBackward()

    {

        //Move him backward

    }

}

 

And Whalla! The robot moves AND I have a record of it!

So add these methods to the MyForm class and you’re done…

 

    private void UnDo()

    {

        m_invoker.Undo(1);

    }

    private void ReDo()

    {

        m_invoker.Redo(1);

    }

 

(Note the “Levels” argument.  That means that we can “Undo” as many times as we have commands)

 

So In the end, you have more code, BUT you’ve created an implmentation of the common Command Pattern. 

 

Plus think of the possiabilities.  Say you need to “Record” a sequence of commands.  You could create a whole bunch of commands as you execute them.  Persist the Invoker collection to disk, and distribute it.  When done that way it’s called a macro.

 

So. The user can’t quite figure out how to push the right buttons in the right order? Load that sequence up and hit play.  Presto! Your done.

 

Drop me a line if you find this article horriable or great.  Either way.  Plus if you have any questions feel free to contact me.


Dave

 

Print | posted on Friday, December 15, 2006 3:21 PM |

Feedback

Gravatar

# re: My take on the command pattern.

excellent article & well written...Thank you
10/16/2008 1:20 AM | Ranu Mandan
Gravatar

# re: My take on the command pattern.

The first thought that came to mind was HM what;s the sun getting ready to do? 2nd thought isn't 2012 coming in about 2 and 1/2 years. 3 Whats going to happen then and no I was not thinking the end of the world but anythings possible. Shake my head the sun is dead, suns die violently my friends, ooooh!
11/25/2008 1:21 PM | Estetik
Gravatar

# re: My take on the command pattern.

Estetik....What the hell are you on about?
11/25/2008 1:26 PM | Dave Redding
Gravatar

# re: My take on the command pattern.

Your Invoker::ExecuteCommand function appears to have a bug. If m_location is less than the length of the command list (i.e. if some commands have been undone, and we want to remove them from the list before adding a new command), you remove commands from the *beginning* of the list. But the most recent commands are stored at the *end* of the list. This means that you could end up re-undoing commands that have already been undone. At least, that's how I understand it. Please correct me if I've missed something.

On a related note, the lines "if (m_location < commands.Count)" and "int i = m_location;" in the same function are redundant. You can remove them and change the while loop to "while (m_location < commands.Count)" and get the same results.

Despite my remarks above, I do think this is rather spiffy. Even the best programmers don't write perfect code every time. The concept is solid (and most of the code is just fine). Good work!
12/12/2008 8:00 PM | Steve
Gravatar

# re: My take on the command pattern.

Thank you very very good
3/24/2009 5:12 PM | plastik cerrahi
Gravatar

# re: My take on the command pattern.

Nice, simple implementation. Good work.

- Comments would be helpful, particularly in this block: if (m_location < commands.Count)
- Commands should have names, so we can display "Undo Move" or whatever in the menu.
- The Invoker should expose whether there are commands to undo.
4/1/2009 3:03 PM | scotch
Gravatar

# re: My take on the command pattern.

I don't understand why this Command implementation uses an abstract Command class with a strongly typed (MyForm) received. A more general approach would be to use an ICommand interface, with only Do/Undo methods. That way you can instantiate a Command anywhere, anyhow.

Invoker implemenation would also be nicer if it used a generic Stack<ICommand> internally, instead of a list.
4/22/2009 4:51 AM | Groo
Gravatar

# re: My take on the command pattern.

You’ve got a lot of cool posts here. Really like it. It served to be helpful. Thanks on that.
4/24/2009 1:14 PM | plastik cerrahi
Gravatar

# re: My take on the command pattern.

I'm guessing the only way to do this in Javascript would be to use the onresize event, and then using the resizeTo method to attempt to keep the window at the size you want?
4/24/2009 6:34 PM | burun estetigi
Gravatar

# re: My take on the command pattern.

I'm guessing the only way to do this in Javascript would be to use the onresize event, and then using the resizeTo method I don't understand why this Command implementation uses an abstract Command class with a strongly typed (MyForm) received. A more general approach would be to use an ICommand interface, with only Do/Undo methods. That way you can instantiate a Command anywhere, anyhow.
4/24/2009 6:35 PM | burun estetigi
Gravatar

# re: My take on the command pattern.

Shake my head the sun is dead, suns die violently my friends, ooooh!
4/28/2009 4:36 PM | yuz estetigi
Gravatar

# re: My take on the command pattern.

good thanks
5/14/2009 5:45 AM | cam balkon
Gravatar

# re: My take on the command pattern.

nice article thanks for sharing, we expect continued success
8/5/2009 5:34 AM | saç ekim
Gravatar

# re: My take on the command pattern.

nice article thank you for sharing, we expect more of the article, successes
8/5/2009 7:54 AM | yüz germe
Gravatar

# re: My take on the command pattern.

We wish you continued success was beautiful page, regards..
8/6/2009 2:25 AM | istanbul minibüs kiralama
Gravatar

# re: My take on the command pattern.

Thank you for this article. It shows a good application for the command pattern. I am just learning about design patterns and most explinations are conceptual with no practical usage. This brings it all down to earth.

Can you do this some more with other design patterns?

Thank you so much!
8/7/2009 7:46 AM | dale
Gravatar

# re: My take on the command pattern.

Can you do this some more with other design patterns?
8/12/2009 6:13 AM | cam balkon
Gravatar

# re: My take on the command pattern.

To make simple commands without having to make a separate class for each command, you can create a default command that takes a delegate, like this:

public class ActionCommand : Command
{
ThreadStart fFunc;
public ActionCommand(ThreadStart func) { fFunction = func; }
public override void Execute() { fFunction(); }
}

And to use it:
Command myCommand = new ActionCommand(delegate
{
// code of the command
});

8/21/2009 4:48 AM | online casinos
Gravatar

# re: My take on the command pattern.

Any guidance for binding these commands to a menustrip/menuitem for enabled/disabled?

8/21/2009 4:50 AM | best online casinos
Gravatar

# re: My take on the command pattern.

This technique plays quite nicely with System.ComponentModel.IExtenderProvider too. You can use that interface to define a component which decorates your user interface controls with command keys, which reference back into a Dictionary of Command objects.

8/21/2009 4:51 AM | casino directory
Gravatar

# re: My take on the command pattern.

This technique plays quite nicely with System.ComponentModel.IExtenderProvider too. You can use that interface to define a component which decorates your user interface controls with command keys, which reference back into a Dictionary of Command objects.
8/22/2009 4:18 PM | koçluk
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification:
 

Powered by: