Net设计模式实例之命令模式(Command Pattern)

一、命令模式简介(Brief Introduction

命令模式(Command Pattern)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。

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

二、解决的问题(What To Solve

       当需要有撤销或者恢复操作时,可以考虑使用命令模式。

三、命令模式分析(Analysis

1、命令模式结构

Command抽象类:声明一个接口,用于执行操作,declares an interface for executing an operation

ConcreteCommand实现类:将一个接收者对象绑定到一个动作。调用接收者相应的操作,以实现Execute

defines a binding between a Receiver object and an action

implements Execute by invoking the corresponding operation(s) on Receiver

Receiver:知道如何执行一个请求相关的操作。knows how to perform the operations associated with carrying out the request.

Invoker:要求命令执行一个请求。asks the command to carry out the request

2、源代码

1Command抽象类声明一个接口,用于执行操作

abstract class Command

{

    protected Receiver receiver;

 

    public Command(Receiver receiver)

    {

        this.receiver = receiver;

    }

    public abstract void Execute();

}

 

2ConcreteCommand具体实现类:将一个接收者对象绑定到一个动作

class ConcreteCommand : Command

{

    // Constructor

    public ConcreteCommand(Receiver receiver)

        :base(receiver)

    {

    }

    public override void Execute()

    {

        receiver.Action();

    }

}

 

3Receiver类:知道如何执行一个请求相关的操作

class Receiver

{

    public void Action()

    {

        Console.WriteLine("Called Receiver.Action()");

    }

}

 

4Invoker类:要求命令执行一个请求

class Invoker

{

    private Command _command;

    public void SetCommand(Command command)

    {

        this._command = command;

    }

    public void ExecuteCommand()

    {

        _command.Execute();

    }

}

 

4、客户端代码

static void Main(string[] args)

{

    // Create receiver, command, and invoker

    Receiver receiver = new Receiver();

    Command command = new ConcreteCommand(receiver);

    Invoker invoker = new Invoker();

 

    // Set and execute command

    invoker.SetCommand(command);

    invoker.ExecuteCommand();

 

    Console.ReadKey();

}

3、程序运行结果

四.案例分析(Example

1、场景

使用命令模式进行计算器计算,可以是加减乘除等运算,可以进行Undo操作和Rodo操作。如下图所示

 

Command抽象命令类:声明一个接口,用于执行操作。

CalculatorCommand具体实现类:将一个接收者对象绑定到一个动作。调用接收者相应的操作,以实现Execute

UnExecute方法:执行Undo操作。

Calculator -Operation方法:执行加减乘除操作。

User:要求命令Calculator执行一个计算请求。

Compute方法:加减乘除等计算操作

Undo方法:撤销操作。Redo方法:重复操作。

2、代码

1、抽象命令类Command及其计算器类CalculatorCommand

/// <summary>

/// The 'Command' abstract class

/// </summary>

abstract class Command

{

    public abstract void Execute();

    public abstract void UnExecute();

}

/// <summary>

/// The 'ConcreteCommand' class

/// </summary>

class CalculatorCommand : Command

{

    private char _operator;

    private int _operand;

    private Calculator _calculator;

    // Constructor

    public CalculatorCommand(Calculator calculator,char @operator, int operand)

    {

        this._calculator = calculator;

        this._operator = @operator;

        this._operand = operand;

    }

    // Gets operator

    public char Operator

    {

        set { _operator = value; }

    }

    // Get operand

    public int Operand

    {

        set { _operand = value; }

    }

    // Execute new command

    public override void Execute()

    {

        _calculator.Operation(_operator, _operand);

    }

    // Unexecute last command

    public override void UnExecute()

    {

        _calculator.Operation(Undo(_operator), _operand);

    }

    // Returns opposite operator for given operator

    private char Undo(char @operator)

    {

        switch (@operator)

        {

            case '+': return '-';

            case '-': return '+';

            case '*': return '/';

            case '/': return '*';

            default: throw new

             ArgumentException("@operator");

        }

    }

}

 

2、计算器类Calculator

/// <summary>

/// The 'Receiver' class

/// </summary>

class Calculator

{

    private int _curr = 0;

    public void Operation(char @operator, int operand)

    {

        switch (@operator)

        {

            case '+': _curr += operand; break;

            case '-': _curr -= operand; break;

            case '*': _curr *= operand; break;

            case '/': _curr /= operand; break;

        }

        Console.WriteLine(

          "Current value = {0,3} (following {1} {2})",

          _curr, @operator, operand);

    }

}

 

3、请求类User

/// <summary>

/// The 'Invoker' class

/// </summary>

class User

{

    // Initializers

    private Calculator _calculator = new Calculator();

    private List<Command> _commands = new List<Command>();

    private int _current = 0;

    public void Redo(int levels)

    {

        Console.WriteLine("\n---- Redo {0} levels ", levels);

        // Perform redo operations

        for (int i = 0; i < levels; i++)

        {

            if (_current < _commands.Count - 1)

            {

                Command command = _commands[_current++];

                command.Execute();

            }

        }

    }

    public void Undo(int levels)

    {

        Console.WriteLine("\n---- Undo {0} levels ", levels);

        // Perform undo operations

        for (int i = 0; i < levels; i++)

        {

            if (_current > 0)

            {

                Command command = _commands[--_current] as Command;

                command.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++;

    }

 

4、客户端代码

static void Main(string[] args)

{

    // Create user and let her compute

    User user = new User();

    // User presses calculator buttons

    user.Compute('+', 100);

    user.Compute('-', 50);

    user.Compute('*', 10);

    user.Compute('/', 2);

    // Undo 4 commands

    user.Undo(4);

    // Redo 3 commands

    user.Redo(3);

    Console.ReadKey();

}

 

3、程序运行结果

五、总结(Summary

命令模式(Command Pattern)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。当需要有撤销或者恢复操作时,可以考虑使用命令模式。

posted @ 2010-01-29 09:58  灵动生活  阅读(3189)  评论(2编辑  收藏  举报