设计模式之command模式

command 模式:
在客户和服务之间增加了一个中间层,使得双方相互独立。即,将命令的发送和接收分离。
而对服务端和客户段可见的只是中间层提供的接口。
command 模式就是面向接口的模式。

中间层将客户端欲调用的所有请求封装成类,客户端一改往日的直接调用命令为调用中间层命令类的对象,从而对客户端屏蔽了所有命令的细节。此法能有效降低耦合度(模块之间的联系程度)。当中间层命令代码改变时无需修改客户端代码。

对command模式uml图的分析:
command模式uml图分为两个部分:
外部视图:用一个参数化的协作来完成,参数说明了该协作实例化时应该实现的角色。

内部视图:用类图来表示结构,用顺序图来表示行为。

由顺序图得知command调用顺序为:
Client发送request给Invoker;
Invoker调用ConcreteCommand的Execute()方法;
Execute()方法调用Receiver的Action()(该Aciton为request的具体实现)。

所涉及的角色:
客户(Client)角色:创建了一个具体命令(ConcreteCommand)对象并确定其接收者。相当于客户端。

命令(Command)角色:声明了一个给所有具体命令类的抽象接口。这是一个抽象角色,(含有Execute()抽象方法) 。

具体命令(ConcreteCommand)角色:定义一个接受者和行为之间的弱耦合,是command接口的实现,实现Execute()方法,负责调用接收到的相应操作。Execute()方法通常叫做执方法。

请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。

接收者(Receiver)角色:负责具体实施和执行一个请求。相当于服务端,任何一个类都可以成为接收者。实施和执行请求的方法叫做行动方法。

具体用到命令模式的例子有界面按钮等操作,ejb调用等。

对于J2EE:

client相当于用户浏览器,发送命令。
Invoker相当于servlet或jsp,它发送客户的请求。
command接口相当于remote接口
ConcreteCommand相当于EJB对象或EJB容器(EJB对象就属于EJB容器,它负责调用Bean的商务方法)。
Receiver相当于具体的企业Bean,用来实现命令请求的细节。

来看一个用command模式实现的计算器程序(C#实现):

1.command抽象类:
abstract class Command  //此处用抽象类来完成接口的工作。
{
  abstract public void Execute();
  abstract public void UnExecute();
}


2.ConcreteCommand:
class CalculatorCommand : Command
{
  // 定义变量
  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; }
  }

  // 覆写command的抽象方法,Execute()。此处的Execute()并没有真正执行命令细节,而是进一步调用receiver的方法,由receiver来执行命令的细节,但对客户端是屏蔽的
  override public void Execute()
  {
    calculator.Operation( @operator, operand );
  }
 
  override public void UnExecute()
  {
    calculator.Operation( Undo( @operator ), operand );
  }

  // undo方法
  private char Undo( char @operator )
  {
    char undo = ' ';
    switch( @operator )
    {
      case '+': undo = '-'; break;
      case '-': undo = '+'; break;
      case '*': undo = '/'; break;
      case '/': undo = '*'; break;
    }
    return undo;
  }
}

3.Receiver:
class Calculator
{
  // 变量
  private int total = 0;

  // 命令的具体实现,仅由command对象来调用,与客户端命令的调用完全独立
  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 );
  }
}


4.Invoker
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 );
    // 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 )
  {
    // 将command对象封装入invoker的Compute里,client只用调用Compute来执行计算,而不用管具体的实现细节。命令的具体实现则由command的Execute()方法来调用Receiver的Operation()来实现

    Command command = new CalculatorCommand(
      calculator, @operator, operand );
    command.Execute();

    // Add command to undo list
    commands.Add( command );
    current++;
  }
}

5.Client:
public class Client
{
  public static void Main( string[] args )
  {
    // 创建用户对象,并发送运算请求和操作数给invoker
    User user = new User();

    user.Compute( '+', 100 );
    user.Compute( '-', 50 );
    user.Compute( '*', 10 );
    user.Compute( '/', 2 );

    // 执行Undo或Redo
    user.Undo( 4 );
    user.Redo( 3 );
  }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值