为了降低系统的耦合度,将事件请求者和接收者解耦,我们可以使用命令模式来设计系统。通过增加不同的命令对象,不仅可以解耦,也可以有效解决发送和接收处理速度不一样的问题。
命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤消的操作。
Command命令接口:
声明执行操作的方法。
ConcreteCommand具体命令类:
通常会持有接收者Receiver,将具体执行业务委托给Receiver。
Invoker请求发送者:
发出请求要求执行操作。
Receiver请求接收者:
接收请求并执行操作。
Client:
调用客户。
类图如下所示:
1 package com.pattern.command; 2 3 // 服务员,相当于Invoker 4 public class Waiter { 5 private Order order = null; 6 7 public void action() { 8 getOrder().cook(); 9 } 10 11 // 下单接口 12 public void setOrder(Order order) { 13 this.order = order; 14 } 15 16 public Order getOrder() { 17 if (order == null) { 18 order = new EmptyOrder(); 19 } 20 return order; 21 } 22 } 23 24 25 26 package com.pattern.command; 27 28 // 厨师,相当于Receiver 29 public class Cooker { 30 // 具体的执行逻辑,烹饪快餐 31 public void cookSimpleMeal() { 32 System.out.println("cook simple meal..."); 33 } 34 35 // 具体的执行逻辑,烹饪招牌菜 36 public void cookPopularMeal() { 37 System.out.println("cook popular meal..."); 38 } 39 } 40 41 42 43 package com.pattern.command; 44 45 // 订单接口,相当于Command 46 public interface Order { 47 public void cook(); 48 } 49 50 51 52 package com.pattern.command; 53 54 // 空的订单,用于代表默认订单 55 public class EmptyOrder implements Order { 56 @Override 57 public void cook() { 58 System.out.println("cooker has no order"); 59 } 60 } 61 62 63 64 package com.pattern.command; 65 66 // 快餐订单,相当于ConcreteCommand 67 public class SimpleOrder implements Order { 68 public Cooker cooker = null; 69 70 public SimpleOrder(Cooker cooker) { 71 this.cooker = cooker; 72 } 73 74 @Override 75 public void cook() { 76 cooker.cookSimpleMeal(); 77 } 78 } 79 80 81 82 package com.pattern.command; 83 84 // 招牌菜订单,相当于ConcreteCommand 85 public class PopularOrder implements Order { 86 public Cooker cooker = null; 87 88 public PopularOrder(Cooker cooker) { 89 this.cooker = cooker; 90 } 91 92 @Override 93 public void cook() { 94 cooker.cookPopularMeal(); 95 } 96 } 97 98 99 100 package com.pattern.command; 101 102 // 订单测试类 103 public class OrderTest { 104 public static void main(String args[]) { 105 // 服务员 106 Waiter waiter = new Waiter(); 107 // 厨师 108 Cooker cooker = new Cooker(); 109 110 waiter.action(); 111 // 下单(快餐) 112 waiter.setOrder(new SimpleOrder(cooker)); 113 waiter.action(); 114 // 下单(招牌菜) 115 waiter.setOrder(new PopularOrder(cooker)); 116 waiter.action(); 117 } 118 }
优点:
1 发起命令的对象和实现命令的对象完全解耦,也就是说发起命令的对象完全不知到具体实现对象是谁,也不知道如何实现。
2 将请求封装起来,可以方便的进行参数扩展、队列化、日志化。
3 可以方便的组合成复合命令(宏命令),更好的复用功能代码。
4 可以方便的扩展新的命令,不用修改已有的代码。
缺点:
1 使用命令模式可能导致某些系统有过多的具体命令类,因为每一个命令都要设计一个具体命令类,所以要根据实际情况判断是否使用。
1 系统需要将请求调用者和接收者解耦,使得调用者和接收者不直接交互。
2 系统需要在不同的时间执行请求。
3 系统需要支持命令的撤消和恢复操作。
4 系统需要将一组操作组合在一起,即支持宏命令。
5 接收者无法及时处理请求,需要异步处理。使用命令队列可以缓存请求,提高系统资源利用率。
6 对于多个需要计时、日志的任务,采用命令可以方便的实现。
1 对于一个场景要不要采用命令模式,主要取决于现有需求及短期很可能扩展的需求。如果不使用模式也能很好的解决,就暂不使用命令模式。因为要引入它并不困难,可以到真正需要它的时候再对系统进行一下整理,引入命令模式。注意:之前的代码要遵循单一指责原则、代码复用原则,这样才能快速的调整代码结构,改进现有的设计。
2 可以创建空命令(EmptyCommand),降低对空指针条件判断的处理。
3 可以创建智慧命令,直接在命令的执行方法中实现业务逻辑,不委托给执行者。
原文:http://www.cnblogs.com/fanyang219/p/6404734.html