I am here to continue the discussion around Design Patterns. Today we will go through one of the behavioral design pattern called Command.
Also in case you have not had a look at our previous articles, go through the following link:
As per GOF guys, Command pattern is defined as in the following.
“Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.”
Well! Let’s understand what they mean and where this pattern can be fit into.
It means that command pattern wraps the requests into objects and hence provides better control over how to manage various user actions.
This can be used in different Windows based applications (Text Editor, Image Editor andCalculator etc.) where we want better control over user actions or commands. In WPF, DelegateCommand, RelayCommand and RoutedCommands are the example of Command pattern.
It is more suited in cases when we want to implement Undo, Redo, and Copy/Paste kind of operations by storing command or action as an object.
If we were to achieve similar control and flexibility without using command pattern, we need to write lot of repeatedcode in various user actions and maintenance of such code becomes difficult for any future change.
Now let’s see the UML of Command pattern.
Command pattern has five key components as following.
- Command: This is an interface that holds the generic methods related to actions.
- Receiver: This class keep the methods for real operations.
- Concreate Command: This class implements the Command interface and invokes the receiver’s operation.
- Invoker: Asks command object to execute the action.
- Client: First creates Concreate Command objects bysetting the receiver then calls the Invoker by setting the concreate command objects.
How Command pattern works?
Invoker calls the Execute methods by passing requests wrapped in command objects. Based on the passed command object, respective concreate command implementation is selected and that in turn invokes the receiver method to do the actual work.
Let's understand this further by simple example.
Let’s begin by creating the Command interface as following.
-
-
-
- public interface ICommand
- {
- bool CanEexecute
- {
- get;
- }
- string Name
- {
- get;
- }
- void Execute();
- }
We also need to create Receiver class to have the actual operations.
-
-
-
- public class Receiver
- {
- public void AddRecord()
- {
- Console.WriteLine("Execute Insert Command");
-
- }
- public void UpdateRecord()
- {
- Console.WriteLine("Execute Update Command");
-
- }
- public void DeleteRecord()
- {
- Console.WriteLine("Execute Delete Command");
-
- }
- }
Now we need to create the concreate command classes by implementing Command interface and having reference to Receiver.
-
-
-
- public class InsertCommand: ICommand
- {
- private Receiver _receiver;
- public InsertCommand(Receiver receiver)
- {
- _receiver = receiver;
- }
- public bool CanEexecute
- {
- get
- {
- return true;
- }
- }
- public string Name
- {
- get
- {
- return "Insert";
- }
- }
- public void Execute()
- {
- _receiver.AddRecord();
- }
- }
-
-
-
- public class UpdateCommand: ICommand
- {…………………….
-
- }
-
-
-
- public class DeleteCommand: ICommand
- {
- private Receiver _receiver;
- public DeleteCommand(Receiver receiver)
- {
- _receiver = receiver;
- }
- public bool CanEexecute
- {
- get
- {
- returnfalse;
- }
- }
- public string Name
- {
- get
- {
- return "Delete";
- }
- }
- public void Execute()
- {
- _receiver.DeleteRecord();
- }
- }
Now comes the Invoker that will be called by Client.
-
-
-
- public class Invoker
- {
- public void ExecuteCommand(ICommand cmd)
- {
- if (cmd.CanEexecute)
- {
- cmd.Execute();
- }
- else
- {
- Console.WriteLine("You don't have permission to execute {0} command", cmd.Name);
- }
- }
- }
At this stage, we are done with defining Command, Receiver, Concreate Commands and Invoker. Now let’s see how client uses them.
- Console.Title = "Command Pattern Demo";
- Receiver rec = newReceiver();
- ICommand insert = newInsertCommand(rec);
- ICommand update = newUpdateCommand(rec);
- ICommand delete = newDeleteCommand(rec);
-
- Invokerinv = newInvoker();
- inv.ExecuteCommand(insert);
- inv.ExecuteCommand(update);
- inv.ExecuteCommand(delete);
Output
As you can see in the output that Insert and Update commands are getting executed whereas Delete command is not. The reason for Delete command not getting executed is the CanExecute property that is returned as false in DeleteCommand class.
I hope you realized the beauty and power of command pattern by going through the example.
A note to add that please keep your command interface and classes clean by just delegating the request to the receiver and let the receiver do the actual implementation.
You can also download the attached demo project (CommandPatternDemo.zip) to go through the full source code referred in the article.
Hope you have liked the article. I look forward for your comments/suggestions.