Gang of Four (GOF) Design Patterns
page 5 of 8
by John Spano
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 39637/ 59

Implementing the Command Pattern in .NET

Level: Beginner + to Object Oriented Programming; Beginner + with .Net and C#

The command pattern is a very useful pattern when you want to give your users the ability to do certain things and undo them.  Typical examples are the undo and redo on many programs today.  This functionality is accomplished with the command pattern.  The GOF book says to use a command pattern when:

1. Parameterize objects by an action to perform
2. Specify, queue, and execute requests at different times
3. Support undo (GOF235)

The pattern encapsulates the commands of your application to self contained classes.   For our example, we will revisit the dog example I have used before and play God for a while.  Our operations will be to magically increase and decrease our bulldog's age.  Since we are almighty, we of course can change our minds and undo our meddling.

First we start with a very simple Bulldog class.

Listing 18

public class CBulldog
{
  private int _Age;
  private string _BarkString;
  public CBulldog()
  {
    _Age = 0;
    _BarkString = "Woof";
  }
  public void Bark()
  {
    Console.WriteLine(_BarkString);
  }
  public int MyAge
  {
    get
    {
      return _Age;
    }
    set
    {
      _Age = value;
    }
  }
  public string MyBark
  {
    get
    {
      return _BarkString;
    }
    set
    {
      _BarkString = value;
    }
  }
}

All the class does is to keep up with the dog’s age, provide a method to change it and allows for the dog to bark.  The bark method writes the dog's bark out to the console window.

For our command classes, we first define three interfaces then our main command classes.  The interfaces allow different kinds of commands to be acted upon as the same type of class.  For our example, we will use two different commands, one to change the dog’s age and another to change how he barks.

First we create our interfaces:

Listing 19

public interface IBaseCommand
{
  void Undo();
}
 
public interface IAgeCommand: IBaseCommand
{
  void AddAge(int age);
}
 
public interface IBarkCommand: IBaseCommand
{
  void ChangeBark(string Newbark);
}

We base the two main command interfaces of a generic one that allows for an undo.  This will allow us to iterate over all interfaces later and undo them as a group.  We can cast any IAgeCommand or IBarkCommand down to an IBaseCommand.

Now for our two classes that encapsulate the commands.  They are pretty straight forward.  Each takes a parameter of the dog to operate on in the constructor and saves off any relevant information like the last age, etc.

Listing 20

public class AgeCommand: IAgeCommand
{
  private CBulldog _OurDog;
  private int _OldAge;
  public AgeCommand(CBulldog o)
  {
    _OurDog = o; //dog to work on
  }
  public void AddAge(int age)
  {
    _OldAge = _OurDog.MyAge;
    _OurDog.MyAge = age;
  }
  public void Undo()
  {
    _OurDog.MyAge = _OldAge;
  }
}
 
public class BarkCommand: IBarkCommand
{
  private CBulldog _OurDog;
  private string _OldBark;
  public BarkCommand(CBulldog o)
  {
    _OurDog = o; //dog to work on
  }
  public void ChangeBark(string Newbark)
  {
    _OldBark = _OurDog.MyBark;
    _OurDog.MyBark = Newbark;
  }
  public void Undo()
  {
    _OurDog.MyBark = _OldBark;
  }
}

Our test of the code will be to create a dog, show its initial settings, change them, show the new settings and then revert back to the original.  For simplicity, we store the list of used commands in an ArrayList object.

Listing 21

CBulldog oDog;
ArrayList cmd = new ArrayList();
 
oDog = new CBulldog();
 
AgeCommand a1 = new AgeCommand(oDog);
Console.WriteLine(oDog.MyAge.ToString());
a1.AddAge(4);
cmd.Add(a1);
Console.WriteLine(oDog.MyAge.ToString());
 
BarkCommand b1 = new BarkCommand(oDog);
oDog.Bark();
b1.ChangeBark("Yip Yip");
cmd.Add(b1);
oDog.Bark();
 
//at this point we have a dog that as beenchanged
//we also have an array that has the command
//objects that were used for the change.
//To undo, just loop through the arraylistbackwards
cmd.Reverse();
foreach (IBaseCommand bse in cmd)
{
  bse.Undo();
}
 
oDog.Bark();
Console.WriteLine(oDog.MyAge.ToString());

View Entire Article

User Comments

No comments posted yet.






Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-04-19 7:19:55 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search