Sitemap
Biswajit Sahoo

Biswajit Sahoo

Software dev who writes about C#, AI, Unity, and XR or anything trending in simpler words.

C# Design Patterns: Command

4 min readJan 5, 2024

--

Press enter or click to view image in full size
Command Design Pattern
Command C# Design Pattern

Thanks for visiting this article. Please scroll down for the bite-sized explanation of this pattern.

Definition

The Command pattern is a behavioral design pattern that allows actions/commands to be represented as objects.

This transformation of actions/commands to “command objects” enables us to create a decoupled and extensible system for 👇

  • passing the commands as method parameters,
  • storing the command in a list/queue for one-by-one execution of commands like in a processing queue,
  • or a stack to help execute undo/redo operations.

separating the requester of an action/command from the invoker or executioner that executes the command.

Press enter or click to view image in full size
Credit: https://unity.com/how-to/use-command-pattern-flexible-and-extensible-game-systems

Let’s understand this from an example

Let’s consider a scenario where a game implements a custom input handling system for player actions such as moving, jumping, and attacking.

We will first create an enum of different input types called InputType.cs

Press enter or click to view image in full size
InputType.cs enum

We will create a Player.cs class with a HandleInput() method that handles all the input types and executes the actions on the player.

Press enter or click to view image in full size
Player.cs class handling the inputs

With the player class handling the inputs, the required actions are being managed in the same class. 😃

But…do you notice a huge problem with the approach above … 😅

❌ As the game grows, the above approach might lead the Player.cs class with numerous switch cases, making it harder to maintain and extend.

❌ Adding new actions or changing existing ones directly modifies the Player.cs class, violating the open-closed principle.

let’s see how using the command pattern solves the problem.

Implementing the Command Pattern

Before we implement, it’s essential to know the components that are part of the implementation.

  1. Command Interface: Represents the command and declares an Execute() method.
  2. Concrete Commands: Implement the Command Interface and encapsulate specific actions (e.g. move, jump, attack).
  3. Invoker: Invokes the commands.
  4. Client: Initiates commands based on player actions.

Let’s call the command interface¹ ICommand.cs which will have the Execute() method.

Press enter or click to view image in full size
ICommand.cs interface

Then, we will create concrete commands² MoveCommand.cs, JumpCommand.cs, and AttackCommand.cs.

Get Biswajit Sahoo’s stories in your inbox

Join Medium for free to get updates from this writer.

For the commands to execute actions on the player, we have to make the Move(), Jump(), and Attack() methods publicly accessible.

Remember each concrete command should only encapsulate a single action and should not contain more than one action.

Press enter or click to view image in full size
MoveCommand.cs concrete command class for the “Move” action
Press enter or click to view image in full size
JumpCommand.cs concrete command class for the “Jump” action
Press enter or click to view image in full size
AttackCommand.cs concrete command class for the “Attack” action

With the concrete commands² created, let's create the invoker³ InputHandler.cs which will be executing these input commands.

As we do not need to check for correct command types anymore, we can get rid of the InputType.cs enum.

Press enter or click to view image in full size
InputHandler.cs invoker class to execute input action “command objects”

Finally, the client⁴ GamePlay.cs is going to initiate these commands for the player.

Press enter or click to view image in full size
GamePlay.cs client class initiating input commands and delegating commands to be executed by the invoker InputHandler

Look… how simple and manageable the inputs are now after implementing the command pattern. 😄 👍 🙌

With this, each command can be stored and reused in any order, allowing a more dynamic input-handling system.

Moreover, if we need to we can keep a buffer of executed commands and then allow re-playing or even undoing the commands. Similar to a strategy or a chess game.

With the implementation, we have achieved 👇

✅ Separation of concerns: Commands encapsulate actions independently of player input handling.

✅ Extensibility & Maintainability: Adding new actions simply requires creating new concrete command classes without modifying the GamePlay.cs or InputHandler.cs class.

But indeed requires the Player.cs class to define public methods for the respective actions, as the player class itself is responsible for managing how the actions are performed by the player.

✅ Undo/Redo: “Command Objects” can be stacked or queued allowing delayed, step-by-step, or repetitive/iterative executions.

Where to use ?

A few use cases could be:

  • Decoupling of Invoker and Receiver: When we want to decouple the object making a request (receiver) from the object that acts (invoker).
  • Undo / Redo operations: When we want to implement undo and redo functionalities in an application. By encapsulating operations as command objects, we can easily revert or replay commands.
  • Queueing and Logging Requests: If we want to log, queue, or schedule requests, the command objects can be stored, logged, and executed later.

And not only limited to the above three cases.

Hope this helped with giving you some clarity on how this pattern can be implemented and used in a real-world scenario.

On the last note. If you like the article please do like and share, and also feel free to provide your valuable comments and feedback.

--

--