"The command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time. The information may include the name of the method, the object that owns the method and possible parameters for it."
"Encapsulate a request as an object, thereby letting users parameterize clients with different requests, queue or log requests, and support undoable operations."
When to use it:
- Queues, sequences or steps of a process which may demand tracking;
- Do and Undo operations;
- Decouple method of object from the invoker in order to make more flexible changes.
Notes:
- Commands can be an example of sub class sandbox pattern;
- Commands may play a role in the chain of responsability pattern;
- Stateless commands very often can be a single static entity.
A base Command defines a interface to assure the existence of the methods Execute() and Unexecute().
/// <summary>
/// The command base class.
/// </summary>
public abstract class Command
{
public abstract void Execute();
}
The Concrete Commands realize the implementation of the base class as well as encapsute the necessary data to call the method Execute().
/// <summary>
/// A command to move a determined object.
/// </summary>
public class MoveObject : BaseMotionAnimation
{
public MoveObject(IMotion entity, Vector3 amount) : base(entity)
{
Start = MotionEntity.transform.position;
Amount = amount;
}
public Vector3 Start { get; }
public Vector3 Amount { get; }
public override void Execute()
{
MotionEntity.Move(Start + Amount);
}
}
The Invoker class has the responsability to invoke commands.
//...
/// Enqueues an animation based on its type.
public void InvokeAnimation(AnimationType type)
{
switch (type)
{
case AnimationType.MoveLeft:
Enqueue(MoveLeft);
break;
case AnimationType.MoveRight:
Enqueue(MoveRight);
break;
case AnimationType.RotateLeft:
Enqueue(RotateLeft);
break;
case AnimationType.RotateRight:
Enqueue(RotateRight);
break;
case AnimationType.ScaleUp:
Enqueue(ScaleUp);
break;
case AnimationType.ScaleDown:
Enqueue(ScaleDown);
break;
}
}
//...
Here are some variations of invokers implementations:
- The Queue is First in First out structure that manipulates commands.
- TimeredQueue works in a similar way, however it only dispatches commands only after an amount of time.
An Actor, a method call and its parameters are the data encapsulated by the concrete commands. The implementation depends completely of the application scope, in this case, a motion object.
//An object in the world
public interface IMotion
{
Transform transform { get; }
void Move(Vector3 amount);
void Scale(Vector3 amount);
void Rotate(Vector3 amount);
}
The Client, makes requests to the invoker to dispatch the commands.
//...
void EnqueueMoveLeft()
{
AnimationQueue.InvokeAnimation(AnimationQueue.AnimationType.MoveLeft);
}
void EnqueueMoveRight()
{
AnimationQueue.InvokeAnimation(AnimationQueue.AnimationType.MoveRight);
}
//...
- Book Game Programming Patterns
- Article Source Making
- Article Habrador
- Github Qian Mo
- Github Naphier
- Youtube Christopher Okhravi
- Youtube Derek Banas
- UML Java Design Patterns