Definition
|
Encapsulate a request as an object, thereby leize you parameterize clients with different requests, queue or log requests, and support undoable operations. |
UML class digoal
Participant
|
The classes and/or objects participating in this pattern are:
- Command(Command)
- Declares an interface for executing an operation
- Concretecommand(Calculatorcommand)
- Defines a binding between a Explorer Object and an action
- Implements execute by invoking the corresponding operation (s) on aggreger
- Client(Commandapp)
- Creates a concretecommand object and sets its aggreger
- Invoker(User)
- Asks the command to carry out the request
- Cycler(Calculator)
- Knows how to perform the operations associated with carrying out the request.
Sample Code in C # This structural code demonstrates the Command pattern which stores requests as objects allowing clients to execute or playback the requests.
// Command pattern -- Structural example |
using System;
// "Command"
abstract class Command
{
// Fields
protected Receiver receiver;
// Constructors
public Command( Receiver receiver )
{
this.receiver = receiver;
}
// Methods
abstract public void Execute();
}
// "ConcreteCommand"
class ConcreteCommand : Command
{
// Constructors
public ConcreteCommand( Receiver receiver ) :
base ( receiver ) {}
// Methods
public override void Execute()
{
receiver.Action();
}
}
// "Receiver"
class Receiver
{
// Methods
public void Action()
{
Console.WriteLine("Called Receiver.Action()");
}
}
// "Invoker"
class Invoker
{
// Fields
private Command command;
// Methods
public void SetCommand( Command command )
{
this.command = command;
}
public void ExecuteCommand()
{
command.Execute();
}
}
/// <summary>
/// Client test
/// </summary>
public class Client
{
public static void Main( string[] args )
{
// Create receiver, command, and invoker
Receiver r = new Receiver();
Command c = new ConcreteCommand( r );
Invoker i = new Invoker();
// Set and execute command
i.SetCommand(c);
i.ExecuteCommand();
}
} |
This real-world code demonstrates the Command pattern used in a simple calculator with unlimited number of Undo's and redo's. note that in C # The word 'operator' is a keyword. prefixing it with '@' allows using it as an identifier.
// Command pattern -- Real World example |
using System;
using System.Collections;
// "Command"
abstract class Command
{
// Methods
abstract public void Execute();
abstract public void UnExecute();
}
// "ConcreteCommand"
class CalculatorCommand : Command
{
// Fields
char @operator;
int operand;
Calculator calculator;
// Constructor
public CalculatorCommand( Calculator calculator,
char @operator, int operand )
{
this.calculator = calculator;
this.@operator = @operator;
this.operand = operand;
}
// Properties
public char Operator
{
set{ @operator = value; }
}
public int Operand
{
set{ operand = value; }
}
// Methods
override public void Execute()
{
calculator.Operation( @operator, operand );
}
override public void UnExecute()
{
calculator.Operation( Undo( @operator ), operand );
}
// Private helper function
private char Undo( char @operator )
{
char undo = ' ';
switch( @operator )
{
case '+': undo = '-'; break;
case '-': undo = '+'; break;
case '*': undo = '/'; break;
case '/': undo = '*'; break;
}
return undo;
}
}
// "Receiver"
class Calculator
{
// Fields
private int total = 0;
// Methods
public void Operation( char @operator, int operand )
{
switch( @operator )
{
case '+': total += operand; break;
case '-': total -= operand; break;
case '*': total *= operand; break;
case '/': total /= operand; break;
}
Console.WriteLine( "Total = {0} (following {1} {2})",
total, @operator, operand );
}
}
// "Invoker"
class User
{
// Fields
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();
private int current = 0;
// Methods
public void Redo( int levels )
{
Console.WriteLine( "---- Redo {0} levels ", levels );
// Perform redo operations
for( int i = 0; i < levels; i++ )
if( current < commands.Count - 1 )
((Command)commands[ current++ ]).Execute();
}
public void Undo( int levels )
{
Console.WriteLine( "---- Undo {0} levels ", levels );
// Perform undo operations
for( int i = 0; i < levels; i++ )
if( current > 0 )
((Command)commands[ --current ]).UnExecute();
}
public void Compute( char @operator, int operand )
{
// Create command operation and execute it
Command command = new CalculatorCommand(
calculator, @operator, operand );
command.Execute(); // Add command to undo list
commands.Add( command );
current++;
}
}
/// <summary>
/// CommandApp test
/// </summary>
public class CommandApp
{
public static void Main( string[] args )
{
// Create user and let her compute
User user = new User();
user.Compute( '+', 100 );
user.Compute( '-', 50 );
user.Compute( '*', 10 );
user.Compute( '/', 2 );
// Undo and then redo some commands user.Undo( 4 );
user.Redo( 3 );
}
}
|
|