一、命令模式简介(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、源代码
1、Command抽象类:声明一个接口,用于执行操作 |
abstract class Command { protected Receiver receiver;
public Command(Receiver receiver) { this.receiver = receiver; } public abstract void Execute(); } |
2、ConcreteCommand具体实现类:将一个接收者对象绑定到一个动作 |
class ConcreteCommand : Command { // Constructor public ConcreteCommand(Receiver receiver) :base(receiver) { } public override void Execute() { receiver.Action(); } } |
3、Receiver类:知道如何执行一个请求相关的操作 |
class Receiver { public void Action() { Console.WriteLine("Called Receiver.Action()"); } } |
4、Invoker类:要求命令执行一个请求 |
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)将请求封装为一个对象,从而使你用不同的请求对客户进行参数化,对请求排队或纪录请求日志,以及支持可撤销的操作。当需要有撤销或者恢复操作时,可以考虑使用命令模式。
版权
作者:灵动生活 郝宪玮
出处:http://www.cnblogs.com/ywqu
如果你认为此文章有用,请点击底端的【推荐】让其他人也了解此文章,
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。