Use Case: GUI Commands, multi undo/redo, need to serialize sequence of actions/calls. There are many use cases!
Code examples below from Dmitri Nesteruk
Definition
The command pattern lets you build an object which represents an instruction to perform a particular action. This command contains all the information needed for the action to be taken.
Command Example
Run a batch of commands on a Bank Account, these commands could then be serialized and persisted to a data store.
- Create
BankAccount
with its methods access modifiers set to internal, this means they are accessible only within files in the same assembly.
1 | public class BankAccount |
- Create our command interface and its implementation.
1 | public interface ICommand |
- Use the commands
1 | var bankAccount = new BankAccount(); |
Composite Command Example
This is a combination of the Composite Pattern and the Command pattern. Building on the example above a Composite Command could be used to transfer money from account A to account B. This will wrap several elements into one element which has the same API.
- Extend the interface to include a
Succcess
property.
1 | public interface ICommand |
- Create a general purpose composite command
1 | public class CompositeBankAccountCommand : List<BankAccountCommand>, ICommand |
- Use the command to test it.
1 | var bankAccount = new BankAccount(); |
- Now to do the money transfer command we need to change how
Call
works as we need to care that the subsequent commands succeeded. This can be accomplished by making theCall
andUndo
methods virtual which allows the implementation to be overridden.
1 | public virtual void Call() { } |
- Create type
MoneyTransferCommand
This is the implementation of a composite command using infrastructure from the above.
1 | public class MoneyTransferCommand : CompositeBankAccountCommand |
- Use the composite command (happy path)
1 | var from = new BankAccount(100); |
- Try transfer more than the balance allows. The overridden call has checks for this so will
Undo
the command and break out of the commands.
1 | var mtc = new CompositeBankAccountCommand(from, to, 1000); |