现在的位置: 首页 > 综合 > 正文

行为型模式一 命令模式

2012年11月29日 ⁄ 综合 ⁄ 共 4480字 ⁄ 字号 评论关闭
Definition

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.

UML class diagram
command[1].gif
Participants

   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 Receiver object and an action
    • implements Execute by invoking the corresponding operation(s) on Receiver
  • Client  (CommandApp)
    • creates a ConcreteCommand object and sets its receiver
  • Invoker  (User)
    • asks the command to carry out the request
  • Receiver  (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 );
  }
}

抱歉!评论已关闭.