Friends, here I am trying to show the usage of Command Design Pattern, one among 23 design patterns.

Personally I like this pattern very much, it is making use of good object oriented constructs and simplifies the logic of enabling Undo. ïŠ

Scenario

You are working on a painting application. For each brush stroke you need to provide the Undo feature.

The brushes presently available are square and rectangle. In future more and more brushes will be available. Our challenge is to provide the user with Undo feature. Clearly, on clicking the undo button, the last stroke should be cleared from the canvas.

Command Pattern applied to the scenario

The definition of Command Pattern says "Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations"

Command Pattern Explained

The pattern says that all the operations should be converted into objects, so that we log the objects. In future we can call Do() or Undo() operations on the object. The object should be smart enough to store the request parameters inside it to support the Do and Undo operations.

Command Pattern for our Scenario

Applied to our scenario, we have got two brushes:

Square Brush

Rectangle Brush

The other parameters would be Canvas which is the PictureBox control on which we draw and the X, Y location on mouse pointer on the canvas. Formulating this we can create 2 classes:

The Do() operation would be drawing a square for the square class and drawing a rectangle for the rectangle class.

We can formulate an interface called ICommand having the Do() and Undo() methods.

publicinterfaceICommand

{

void Do();

void Undo();

}

The classes would be SquareCommand and RectangleCommand which implement s the above interface.

Architecture - Class Diagram

Implementation

When the application is executed, the user will be having a blank white screen, with a set of colors to choose from. The default brush selected will be Square and on clicking the canvas a new square will be drawn on the canvas. The default color selected is Blue and is stored in the variable _activeColor.

The form level variables declared are:

privateShapeEnum _activeShape = ShapeEnum.Square;

privateColor _activeColor = Color.Blue;

privateBitmap _bitmap;

privateGraphics _graphics;

For each mouse down operation a new square class will be created. That means if 10 clicks are made 10 square classes will be created and the Do() operation is called An enumeration variable called _activeShape is used to keep track of the current shape selected by the user. The mouse down event would look like the following.

privatevoid Canvas_MouseDown(object sender, MouseEventArgs e)

{

// Each mouse down creates a new command class instance

ICommand command = null;

if (_activeShape == ShapeEnum.Square)

command = newSquareCommand(_bitmap, _activeColor, e.X, e.Y);

elseif (_activeShape == ShapeEnum.Rectangle)

command = newRectangleCommand(_bitmap, _activeColor, e.X, e.Y);

command.Do();

_commandStack.Push(command);

RefreshUI();

}

Let us take an example: assume the user clicked the mouse at Point X=100 and Y=200. As the _activeShape is Square, a new SquareCommand class instance is created with arguments e.X and e.Y. The remaining arguments are bitmap and the active color. Then the command instance would be pushed to a stack and the Do() operation is called.

The stack provides a storage for usage of the command instance later. The declaration of stack is:

privateStack<ICommand> _commandStack = newStack<ICommand>();

Inside the SquareCommand Class

We can have a look on the Square class. Both the SquareCommand and RectangleCommand class will be having same implementations except in the Do() operation of drawing the respective shape.

publicclassSquareCommand : ICommand

{

privatePoint _point;

privateBitmap _bitmap;

privateGraphics _graphics;

privateColor _color;

public SquareCommand(Bitmap bitmap, Color color, int x, int y)

{

_bitmap = bitmap;

_graphics = Graphics.FromImage(_bitmap);

_color = color;

_point = newPoint(x, y);

}

publicvoid Do()

{

// Save the current pixel colors for a future UNDO perform

SaveCurrentPixels();

// Do the drawing

_graphics.FillRectangle(newSolidBrush(_color),

newRectangle(_point.X, _point.Y, Width, Height));

}

privateconstint Width = 50;

privateconstint Height = 50;

privateIList<Color> _colors = newList<Color>();

privatevoid SaveCurrentPixels()

{

for (int i = _point.X; i < _point.X + Width; i++)

for (int j = _point.Y; j < _point.Y + Height; j++)

_colors.Add(_bitmap.GetPixel(i, j));

}

///<summary>

/// Perform Undo by restoring back the pixels to previous colors

///</summary>

publicvoid Undo()

{

int ix = 0;

for (int i = _point.X; i < _point.X + Width; i++)

for (int j = _point.Y; j < _point.Y + Height; j++)

_bitmap.SetPixel(i, j, _colors[ix++]);

}

}

The constructor is called with the bitmap and the x, y positions which are then stored into class fields. When the Do() method is called the current pixel colors are saved into the _colors list. This would enable us to perform the Undo() method later. After that the graphics.FillRectangle() method is called to draw the square. The width and height of the square would be set to 50 pixels using the constants Width and Height respectively.

The Undo() method just restores the previous pixel values using the bitmap.SetPixel method() by iterating through each pixel starting from x, y position.

Performing the Undo() on clicking Undo button

As we encapsulated each operation to a class with parameters and logged them into the command stack, it is now easier to call the Undo() method. Please remind that on clicking the Undo button we have to get the last operation instance and call the Undo() method of it, and removing it from the stack.

The code for it is:

privatevoid UndoButton_Click(object sender, EventArgs e)

{

// Check command stack contains items

if (_commandStack.Count > 0)

{

// Remove the last command

ICommand lastCommand = _commandStack.Pop();

// Call the Undo method

lastCommand.Undo();

}

RefreshUI();

}

First, the command stack count is checked to ensure there are commands inside it. Then the last command is popped out using the Pop() method. It will give us the last instance in the stack as well as removes it. Then, the Undo() operation is invoked. After, the RefreshUI() method is called to update the UI with the changes.

Note

The command pattern provides an object oriented manner to provide Undo feature to our application in a flexible manner.

But the creation of lot of object instances is one of the draw back of this method which usually people say about. I would say that in the other hand, the command pattern is giving us the advantage of keeping the code more manageable.

Jean Paul is a Developer plus Architect working on Microsoft Technologies for the past 12 years. He is very much passionate in programming and his core skills are SharePoint, ASP.NET & C#.
In the academic side... Read more