首页 > 代码库 > 设计模式之命令模式学习理解

设计模式之命令模式学习理解

命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

 

介绍

意图:将一个请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。

主要解决:在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

何时使用:在某些场合,比如要对行为进行"记录、撤销/重做、事务"等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将"行为请求者"与"行为实现者"解耦?将一组行为抽象为对象,可以实现二者之间的松耦合。

如何解决:通过调用者调用接受者执行命令,顺序:调用者→接受者→命令。

关键代码:定义三个角色:1、received 真正的命令执行对象 2、Command 3、invoker 使用命令对象的入口

应用实例:struts 1 中的 action 核心控制器 ActionServlet 只有一个,相当于 Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的 Command。

优点: 1、降低了系统耦合度。 2、新的命令可以很容易添加到系统中去。

缺点:使用命令模式可能会导致某些系统有过多的具体命令类。

使用场景:认为是命令的地方都可以使用命令模式,比如: 1、GUI 中每一个按钮都是一条命令。 2、模拟 CMD。

注意事项:系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,也可以考虑使用命令模式,见命令模式的扩展。

 

假设现在有个创建工单的类,还有个安装工的类负责接收和安装工单。

简单的紧耦合实现

 1 /**
 2  * 新建工单类
 3  * @author ko
 4  *
 5  */
 6 public class NewlyBuildOrder {
 7 
 8     public void buildTypeAOrder(){
 9         System.out.println("build type a order...");
10     }
11     
12     public void buildTypeBOrder(){
13         System.out.println("build type b order...");
14     }
15     
16 }
 1 /**
 2  * 安装工
 3  * 接单并安装
 4  * @author ko
 5  *
 6  */
 7 public class Installer {
 8     
 9     public void receiveInstall(NewlyBuildOrder newlyBuildOrder){
10         
11         newlyBuildOrder.buildTypeAOrder();
12         newlyBuildOrder.buildTypeBOrder();
13         newlyBuildOrder.buildTypeAOrder();
14         newlyBuildOrder.buildTypeAOrder();
15         
16     }
17     
18 }
 1 /**
 2  * 测试类
 3  * 新建工单
 4  * 安装工领取并安装工单
 5  * @author ko
 6  *
 7  */
 8 public class Test {
 9 
10     public static void main(String[] args) {
11         NewlyBuildOrder newlyBuildOrder = new NewlyBuildOrder();
12         Installer installer = new Installer();
13         installer.receiveInstall(newlyBuildOrder);
14     }
15 }
build type a order...
build type b order...
build type a order...
build type a order...

这其实是行为请求者和行为实现者的紧耦合,这样写有很多弊端,如果安装工多了,那就会很混乱,没有日志记录,另外需要撤销领取的工单重新领取也不行。

松耦合命令模式实现

 1 // 把行为请求者对行为实现者的命令抽象成类
 2 public abstract class Command {
 3 
 4     protected NewlyBuildOrder newlyBuildOrder;
 5 
 6     public Command(NewlyBuildOrder newlyBuildOrder){
 7         this.newlyBuildOrder = newlyBuildOrder;
 8     }
 9     
10     // 执行命令
11     public abstract void excuteCommand();
12     
13 }
 1 // A类工单命令
 2 public class TypeAOrderCommand extends Command {
 3 
 4     public TypeAOrderCommand(NewlyBuildOrder newlyBuildOrder) {
 5         super(newlyBuildOrder);
 6         // TODO Auto-generated constructor stub
 7     }
 8 
 9     @Override
10     public void excuteCommand() {
11         newlyBuildOrder.buildTypeAOrder();
12     }
13 
14     @Override
15     public String toString() {
16         return "TypeAOrderCommand";
17     }
18 
19 }
 1 // B类工单命令
 2 public class TypeBOrderCommand extends Command {
 3 
 4     public TypeBOrderCommand(NewlyBuildOrder newlyBuildOrder) {
 5         super(newlyBuildOrder);
 6         // TODO Auto-generated constructor stub
 7     }
 8 
 9     @Override
10     public void excuteCommand() {
11         newlyBuildOrder.buildTypeBOrder();
12     }
13 
14     @Override
15     public String toString() {
16         return "TypeBOrderCommand";
17     }
18 
19 }
 1 /**
 2  * 工单管理
 3  * 介于行为请求者和行为实现者之间的类
 4  * @author ko
 5  *
 6  */
 7 public class OrderManage {
 8 
 9     private List<Command> orders = new ArrayList<>();// 存放具体命令的容器
10     
11     // 设置订单
12     // 对于工单管理类,不管安装工想要的是什么类型的工单,反正都是‘命令’,只管记录订单,
13     // 
14     public void setOrder(Command command){
15         if (command.toString().equals("TypeAOrderCommand")) {
16             System.out.println("type a order is over, can‘t provide ...");
17         }else{
18             orders.add(command);
19             // 打印日志
20             System.out.println("LOG   add order:"+command.toString()+",time:"+System.currentTimeMillis());
21         }
22     }
23     
24     // 撤销订单
25     public void revokeOrder(Command command){
26         orders.remove(command);
27         // 打印日志
28         System.out.println("LOG   revoke order:"+command.toString()+",time:"+System.currentTimeMillis());
29     }
30     
31     public void notifyBuilder(){
32         for (Command command : orders) {
33             command.excuteCommand();
34         }
35     }
36     
37 }
 1 /**
 2  * 新建工单类
 3  * @author ko
 4  *
 5  */
 6 public class NewlyBuildOrder {
 7 
 8     public void buildTypeAOrder(){
 9         System.out.println("build type a order...");
10     }
11     
12     public void buildTypeBOrder(){
13         System.out.println("build type b order...");
14     }
15     
16 }
 1 /**
 2  * 测试类
 3  * @author ko
 4  *
 5  */
 6 public class Test {
 7 
 8     public static void main(String[] args) {
 9         // 初始准备
10         NewlyBuildOrder newlyBuildOrder = new NewlyBuildOrder();
11         Command typeAOrderCommand = new TypeAOrderCommand(newlyBuildOrder);
12         Command typeBOrderCommand = new TypeBOrderCommand(newlyBuildOrder);
13         OrderManage orderManage = new OrderManage();
14 
15         // 设置命令
16         orderManage.setOrder(typeAOrderCommand);
17         orderManage.setOrder(typeBOrderCommand);
18         
19         // 通知order builder
20         orderManage.notifyBuilder();
21         
22     }
23 }
type a order is over, can‘t provide ...
LOG   add order:TypeBOrderCommand,time:1500879972241
build type b order...

  

设计模式之命令模式学习理解