Categories: Design Pattern

Behavioral Patterns – Command

Command – It turns the client’s requests into a stand-alone object which contains all information about the client’s requests. These transformations let the programs pass the client requests to method arguments, delay or queue the client’s execution, and undoable operations.

From Design Pattern – Behavioral Patterns

Structure

Command pattern – Class diagram UML

Applicability

  • Using its pattern is when the program requests want to parameterize objects with operations.
  • Using its pattern is when the programs want to queue operations, schedule their execution, or execute them remotely.
  • Using its pattern is when the programs want to implement reversible operations.

Pros and Cons

PROS

  • Single Responsibility Principle – It can decouple classes which invoke operations from the classes that perform these operations.
  • Open-closed principle- It can introduce a new command into the apps without breaking existing client code.
  • It can implement undo or redo, and deferred execution of operations.
  • It can assemble a set of simple commands into a complex one.

CONS

  • The code may become more complex since the developers are introducing a whole new layer between senders and recivers.

How to Implement

#1 Basic Sample

class Program
{   
 static void Main(string[] args)
 {
  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();

  Console.ReadKey();
 }

 public class Receiver
 {
  public void DoSomething(string a) => Console.WriteLine($"Receiver: Working on {a}.");

  public void DoSomethingElse(string a) => Console.WriteLine($"Receiver: Also working on {a}.");
 }

 public interface ICommand
 {
  void Execute();
 }

 public class SimpleCommand : ICommand
 {
  private string _payload = string.Empty;

  public SimpleCommand(string payload)
  {
   _payload = payload;
  }

  public void Execute() => Console.WriteLine($"SimpleCommand: See, I can do simple things like printing ({this._payload})");
 }

 public class ComplexCommand : ICommand
 {
  private Receiver _receiver;

  private string _a = string.Empty;

  private string _b = string.Empty;

  public ComplexCommand(Receiver receiver, string a, string b)
  {
   _receiver = receiver;
   _a = a;
   _b = b;
  }

  public void Execute()
  {
   Console.WriteLine("ComplexCommand: Complex stuff should be done by a receiver object.");
   _receiver.DoSomething(_a);
   _receiver.DoSomethingElse(_b);
  }
 }

 public class Invoker
 {
  private ICommand _onStart;

  private ICommand _onFinish;

  public void SetOnStart(ICommand command) => _onStart = command;

  public void SetOnFinish(ICommand command) => _onFinish = command;

  public void DoSomethingImportant()
  {
   Console.WriteLine("Invoker: Does anybody want something done before I begin?");

   if (_onStart is ICommand)
    _onStart.Execute();

   Console.WriteLine("Invoker: ...doing something really important...");

   Console.WriteLine("Invoker: Does anybody want something done after I finish?");

   if (_onFinish is ICommand)
    _onFinish.Execute();
  }
 }
}

#2 Web Application Project

Step 1 Create the interface class and the service class in the Core project. The interface class file name sets the “ICommand” and “ICommandExe.” One the interface class is for the BLL to create. Another interface class file is for the command pattern executing. The service class part also does the same things and has three files. One service class file is for the BLL. Another service class file is for the command pattern progress. Other service class files are also for the command pattern progress, but one part is different, which means it does other things.

Fig 1 Solution explorer – Command pattern

Step 2 Adding the task in the ICommandExe interface class file with the generic type mechanism. The ICommand interface class file adds the task result, the setting on the start function, and the finish function. The ICommand interface class file increased minor difficulty levels, adding the “in” and “out” operator mechanisms. I hope it can increase the sample complex and approach the real-time situation.

Fig 2 ICommand interface class source code
public interface ICommand<in T1, out T2> where T1: class where T2: class
{
 Task<List<T>> ExecuteResult<T>(T1 requestObj);

 void SetOnStart(ICommandExe commandExe);

 void SetOnFinsh(ICommandExe commandExe);
}
Fig 3 ICommandExe interface class source code
public interface ICommandExe
{
 Task<T> Execute<T>(object obj, object reqObj) where T : class;
}

Step 3 The service part files let us start from the CommandService class file to edit. The CommandService class file must inherit the ICommand interface class, then add the IGenericTypeRepository interface class by DI mechanism and a few variables and functions. Suppose the data has been accessed before the command pattern operations. The command service class file can focus on the command pattern concept to edit. Remember that the ICommand interface class file has the “in” and “out” operator mechanism, so the developers must be careful to edit it.

Fig 4 CommandServices class source code

Step 4 The CommandExeService class file will focus on the command pattern operation executing. It inherits the ICommandExe interface class files, then adds the private function about the command operation progress in the CommandExeService class file.

Fig 5 CommandExeServices class source code

Step 5 Create the command pattern-related files in the Web project, such as the controller and view parts. A view part only creates the index page without the CRUD page.

Fig 6 Command pattern solution explorer – Web project

Step 6 Register the command pattern’ service class files and the interface class files in the Web project.

Fig 7 Command pattern result

Reference

davidsky69

View Comments

Recent Posts

API Gateway in .NET 5 with Ocelot

What is the API gateway? An API gateway is an API management tool that sits…

3 years ago

.NET 5 application with Onion architecture

The .NET 5 SDK is a kind of milestone in the .NET world. The .NET…

3 years ago

SOLID Principles – Dependency inversion principle

In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupling software…

4 years ago

SOLID Principles – Interface segregation principle

In the field of software engineering, the interface segregation principle (ISP) states that no code…

4 years ago

SOLID Principles – Liskov substitution principle

Subtype Requirement: Let  be a property provable about objects  of type T. Then  should be true for objects  of type S where S is…

4 years ago

SOLID Principles – Open-closed principle

In object-oriented programming, the open–closed principle states "software entities (classes, modules, functions, etc.) should be…

4 years ago