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

3.命令模式

2016年02月27日 ⁄ 综合 ⁄ 共 4657字 ⁄ 字号 评论关闭

本文作者: ImportNew -
hejiani
未经许可,禁止转载!

概述

在面向对象编程中,命令模式属于行为型(behavior)设计模式,用于“行为发送者”与“行为接收者”之间的解耦。(行为发送者为发起某个操作的对象,接收者为执行该操作请求的对象)。命令模式的结构如下图所示:

命令模式结构图命令模式结构图

命令模式的常见使用场景有:

  • Java 菜单项和按钮的动作处理
  • 为宏(复合命令)提供支持(记录和回退的宏操作)
  • “undo”操作
  • Java进度条
  • 日志、请求队列等

使用命令模式实现事务

假定需要TCP端口连接的用于接受和处理用户请求事务的服务器,这些事务包含很多命令。如果使用switch语句在case中调用每个命令,会导致程序耦合度增加,不符合面向对象设计思想。将这些命令封装为对象将请求者和接受者解耦,这样的设计更加合适。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import
java.util.*;
final
class
CommandReceiver {
  private
int[] c;
  private
CommandArgument a;
     private
CommandReceiver(){
       c =
new int[2];
     }
     private
static CommandReceiver cr =
new CommandReceiver();
     public
static CommandReceiver getHandle() {
     return
cr;
     }
     public
void setCommandArgument(CommandArgument a) {
     this.a = a;
     }
     public
void methAdd() {
     c = a.getArguments();
         System.out.println("The result is "
+ (c[0]+c[1]));
     }
     public
void methSubtract() {
     c = a.getArguments();
         System.out.println("The result is "
+ (c[0]-c[1]));
     }
}

命令模式代码类图命令模式代码类图

CommandReceiver是命令接收者角色,实现了所有的命令处理方法,同时它作为单例实现。

1
2
3
4
5
6
7
8
9
class
CommandManager {
  private
Command myCommand;
  public
CommandManager(Command  myCommand) {
    this.myCommand  =  myCommand ;   
  }
  public
void runCommands( ) {
           myCommand.execute();    
  }
}

CommandManager是调用者角色,它的私有变量myCommand传入TransactionCommand对象。当runCommands()被调用时,选择合适的TransactionCommand对象的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class
TransactionCommand
implements
Command {
  private
CommandReceiver commandreceiver;
  private
Vector commandnamelist,commandargumentlist;
  private
String commandname;
  private
CommandArgument commandargument;
  private
Command command;
  public
TransactionCommand () {
    this(null,null);
  }
  public
TransactionCommand ( Vector  commandnamelist, Vector
commandargumentlist){
    this.commandnamelist = commandnamelist;
    this.commandargumentlist = commandargumentlist;
    commandreceiver =  CommandReceiver.getHandle(); 
  }
  public
void execute( ) {
    for
(int
i =
0; i < commandnamelist.size(); i++) {
      commandname = (String)(commandnamelist.get(i));
      commandargument = (CommandArgument)((commandargumentlist.get(i)));
      commandreceiver.setCommandArgument(commandargument);
      String classname = commandname +
"Command";
         try
{
           Class cls = Class.forName(classname);
           command = (Command) cls.newInstance();
         }
         catch
(Throwable e) {  
                  System.err.println(e);
         }
      command.execute();
    }
  }
}
 class
AddCommand extends
TransactionCommand {
   private
CommandReceiver cr;
   public
AddCommand () {
      cr = CommandReceiver.getHandle(); 
   
   public
void execute( ) { 
     cr.methAdd(); 
   }  
 }
 class
SubtractCommand extends
TransactionCommand {
   private
CommandReceiver cr;
   public
SubtractCommand () {
      cr = CommandReceiver.getHandle(); 
   }
   public
void execute( ) {
     cr.methSubtract();
   }  
 }

TransactionCommand对象的execute()操作根据传递的命令名称列表的内容动态加载需要的命令子类(子类命名时遵守操作名 + “Command”的命名习惯)。

命令和参数存储在list中,封装在TransactionCommand对象中。

1
2
3
4
5
6
7
8
9
10
11
12
class
CommandArgument {
  private
int[] args;
  CommandArgument() {
    args =
new int[2];
  }
  public
int[] getArguments() {
   return
args;
  }
  public
void setArgument(int
i1, int
i2) {
        args[0] = i1; args[1] =
i2;
  }
}

CommandArgument是辅助类,用来保存命令参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public
class
TestTransactionCommand {
  private 
Vector clist,alist;
  public
TestTransactionCommand() {
    clist =
new Vector();
      alist =
new Vector();
  }
  public
void clearBuffer(Vector c, Vector a) {
    clist.removeAll(c);
      alist.removeAll(a);
  }
  public
Vector getClist() {
    return
clist;
  }
  public
Vector getAlist() {
    return
alist;
  }
   public
static void
main(String[] args) {
      CommandArgument ca,ca2;
    TestTransactionCommand t =
new TestTransactionCommand();
    ca =
new CommandArgument();
    ca.setArgument(2,8);
    Vector myclist = t.getClist();
    Vector myalist = t.getAlist();
    myclist.addElement("Add"); myalist.addElement(ca);
    TransactionCommand tc =
new TransactionCommand(myclist,myalist);
    CommandManager cm =
new CommandManager(tc);      
                   cm.runCommands();
    t.clearBuffer(myclist,myalist);
    ca2 =
new CommandArgument();
    ca2.setArgument(5,7);
    myclist = t.getClist();
    myalist = t.getAlist();
    myclist.addElement("Subtract"); myalist.addElement(ca2);
    myclist.addElement("Add"); myalist.addElement(ca2);
    TransactionCommand tc2 =
new TransactionCommand(myclist,myalist);       
    CommandManager cm2 =
new CommandManager(tc2);      
                   cm2.runCommands();
  }
}

可见,客户端的代码不依赖于任何的TransactionCommand子类,同时具有良好的可扩展性——需要增加新命令时可以定义子类并在CommandReceiver类提供新的命令处理方法。

总结

  • Command是整个模式的核心,Command的实现类是接收者和调用者的桥梁,接收者与命令实现类相关联,调用者发出请求到某个命令。
  • 具体的请求封装为命令对象,将命令存储在调用者对象中,使得不同动作的组合以及动作记录更加容易实现。
  • 增加新的命令时,不需要修改已有的代码。
  • 缺点:可能导致系统有过多的命令类以及复杂的关联关系。

抱歉!评论已关闭.