十七.行为型设计模式——Command Pattern(命令模式)

  • 定义

  将一个请求封装成一个对象,因此可以参数化多个客户的不同请求,将请求排队,记录请求日志,并且支持撤销操作。

  UML类图如下:

  

  其中类和对象之间的关系为:

  1. Command(抽象命令):声明执行操作的一个接口。

  2. ConcreteCommand(具体命令类):将一个接收者对象绑定于一个动作;实现Execute方法,以调用接收者的相关的操作(Action)。

  3. Client(客户应用程序):创建一个具体命令类的对象,并且设定它的接收者。

  4. Invoker(调用者):要求一个命令对象执行一个请求。

  5. Receiver(接收者):知道如何执行关联请求的相关操作。

  典型应用的顺序图:

  

  • 实例1——简单计算器

  把命令模式应用于一个简单计算器程序,可以产生无限个Redo(重做)和Undo(取消)操作,UML类图如下:

  

  

代码
//抽象命令类
abstract class Command
{
abstract public void Execute();
abstract public void UnExecute();
}
//具体命令类
class CalculatorCommand : Command
{
private char @operator;
int operand;
Calculator calculator;
public CalculatorCommand(Calculator calculator,char @operator,int operand)
{
this.calculator = calculator;
this.@operator = @operator;
this.operand = operand;
}
public char Operator
{
set { @operator = value; }
}
public int Operand
{
set { operand = value; }
}
public override void Execute()
{
calculator.Operation(@operator, operand);
}
public override void UnExecute()
{
calculator.Operation(Undo(@operator), operand);
}
private char Undo(char @operator)
{
char undo = ' ';
switch (@operator)
{
case '+': undo = '-'; break;
case '-': undo = '+'; break;
case '*': undo = '/'; break;
case '/': undo = '*'; break;
}
return undo;
}
}

//接收者
class Calculator
{
private int total = 0;
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);
}
}

//调用者
class User
{
private Calculator calculator = new Calculator();
private ArrayList commands = new ArrayList();
private int current = 0;
public void Redo(int levels)
{
Console.WriteLine(
"------ Redo {0} levels", levels);
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);
for (int i = 0; i < levels; i++)
{
if (current >0)
{
((Command)commands[
--current]).UnExecute();
}
}
}
public void Compute(char @operator, int operand)
{
//生成命令并且执行它
Command command = new CalculatorCommand(calculator, @operator, operand);
command.Execute();
//在取消列中增加这个命令
commands.Add(command);
current
++;
}
}

//客户应用测试
class Client
{
[STAThread]
static void Main(string[] args)
{
User user
= new User();
user.Compute(
'+', 100);
user.Compute(
'-', 50);
user.Compute(
'*', 10);
user.Compute(
'/', 2);
//取消,重做一些命令
user.Undo(4);
user.Redo(
3);
Console.Read();
}
}

 

 

  • 优势和缺陷

  命令模式分离了接受请求的对象与实现处理请求工作的对象,这样,已经存在的类可以保持不变,使得增加新类的工作更简单。例如,很多软件的宏命令就提高了系统的自动化程度。

  命令模式还可以分离用户界面和业务对象,降低系统的耦合度。

  但是,命令模式最主要的缺陷就是,类的数量增加了,系统变得更复杂,程序的调试工作也相应变得困难。

  • 应用情景

  下面的情景很适合应用命令模式:

  1. 当你需要与工作相关的对象来作为参数。

  2. 你需要在不同的时间创建请求,生成请求队列,执行请求。

  3. 你需要支持取消、保存修改日志或处理事务功能。

  4. 你需要支持宏命令。

posted on 2010-11-15 23:14  tLEE  阅读(613)  评论(0编辑  收藏  举报

导航