The next design pattern in the Behavioral Category is the Command Design Pattern. Let's take a look at this design pattern and see when and how to implement this in C# and .Net.
Note: Code can be downloaded at my Github.
1. What is the Command Design Pattern?
The Command Design Pattern is used to turn a request into a stand-alone object which has all information about the request. By doing so, the methods for requests can be parameterized and invoked once in need to use.
The command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.
2. When to implement the Command Design Pattern?
You may want to use the Command Design Pattern when:
- You want to parameterize objects with operations
- You want to queue operations, schedule the executions or execute them remotely
- You want to reverse the operation
3. How to implement the Command Design Pattern?
Below are steps to implement the Command Design Pattern in C# and .Net
Step 1: Create a Command Interface
The Command interface declares a method for executing a command
1 2 3 4 | public interface ICommand { void Execute(); } |
Step 2: Create Command Classes
Some commands can implement simple operations on their own. However, some commands can delegate more complex operations to other objects, called "receivers."
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | class SimpleCommand : ICommand { private string _payload = string .Empty; public SimpleCommand( string payload) { this ._payload = payload; } public void Execute() { Console.WriteLine($ "SimpleCommand: See, I can do simple things like printing ({this._payload})" ); } } class ComplexCommand : ICommand { private Receiver _receiver; // Context data, required for launching the receiver's methods. private string _a; private string _b; // Complex commands can accept one or several receiver objects along // with any context data via the constructor. public ComplexCommand(Receiver receiver, string a, string b) { this ._receiver = receiver; this ._a = a; this ._b = b; } // Commands can delegate to any methods of a receiver. public void Execute() { Console.WriteLine( "ComplexCommand: Complex stuff should be done by a receiver object." ); this ._receiver.DoSomething( this ._a); this ._receiver.DoSomethingElse( this ._b); } } |
Step 3: Create an Invoker and a Receiver class
The Receiver classes contain some important business logic. They know how to perform all kinds of operations, associated with carrying out a request. In fact, any class may serve as a Receiver.
The Invoker is associated with one or several commands. It sends a request to the command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | class Receiver { public void DoSomething( string a) { Console.WriteLine($ "Receiver: Working on ({a}.)" ); } public void DoSomethingElse( string b) { Console.WriteLine($ "Receiver: Also working on ({b}.)" ); } } // The Invoker is associated with one or several commands. It sends a // request to the command. class Invoker { private ICommand _onStart; private ICommand _onFinish; // Initialize commands. public void SetOnStart(ICommand command) { this ._onStart = command; } public void SetOnFinish(ICommand command) { this ._onFinish = command; } public void DoSomethingImportant() { Console.WriteLine( "Invoker: Does anybody want something done before I begin?" ); if ( this ._onStart is ICommand) { this ._onStart.Execute(); } Console.WriteLine( "Invoker: ...doing something really important..." ); Console.WriteLine( "Invoker: Does anybody want something done after I finish?" ); if ( this ._onFinish is ICommand) { this ._onFinish.Execute(); } } } |
Done, you can execute the code on the client to see the result.
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Program { static void Main( string [] args) { // The client code can parameterize an invoker with any commands. Invoker invoker = new Invoker(); invoker.SetOnStart( new SimpleCommand( "Say Hi!" )); Receiver receiver = new Receiver(); invoker.SetOnFinish( new ComplexCommand(receiver, "Send email" , "Save report" )); invoker.DoSomethingImportant(); } } |
Output:
4. Conclusion
The Command Design Pattern is useful for your applications if you need to control when to invoke the received requests. I hope this tutorial is helpful. Please let me know your thoughts in the comment section below.