首页 > 其他 > 详细

设计模式-命令模式

时间:2017-02-16 14:20:46      阅读:208      评论:0      收藏:0      [点我收藏+]

1 模式动机

    为了降低系统的耦合度,将事件请求者和接收者解耦,我们可以使用命令模式来设计系统。通过增加不同的命令对象,不仅可以解耦,也可以有效解决发送和接收处理速度不一样的问题。

 

2 模式定义

   命令模式(Command Pattern):将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤消的操作。

 

3 模式分析

Command命令接口:

    声明执行操作的方法。

ConcreteCommand具体命令类:

    通常会持有接收者Receiver,将具体执行业务委托给Receiver

Invoker请求发送者:

    发出请求要求执行操作。

Receiver请求接收者:

    接收请求并执行操作。

Client:

    调用客户。

类图如下所示:

 技术分享

4 实例演示

  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 }

 

5 优缺点

优点:

1 发起命令的对象和实现命令的对象完全解耦,也就是说发起命令的对象完全不知到具体实现对象是谁,也不知道如何实现。

2 将请求封装起来,可以方便的进行参数扩展、队列化、日志化。

3 可以方便的组合成复合命令(宏命令),更好的复用功能代码。

4 可以方便的扩展新的命令,不用修改已有的代码。

缺点:

1 使用命令模式可能导致某些系统有过多的具体命令类,因为每一个命令都要设计一个具体命令类,所以要根据实际情况判断是否使用。

 

6 适用环境

1 系统需要将请求调用者和接收者解耦,使得调用者和接收者不直接交互。

2 系统需要在不同的时间执行请求。

3 系统需要支持命令的撤消和恢复操作。

4 系统需要将一组操作组合在一起,即支持宏命令。

5 接收者无法及时处理请求,需要异步处理。使用命令队列可以缓存请求,提高系统资源利用率。

6 对于多个需要计时、日志的任务,采用命令可以方便的实现。

 

7 总结

1 对于一个场景要不要采用命令模式,主要取决于现有需求及短期很可能扩展的需求。如果不使用模式也能很好的解决,就暂不使用命令模式。因为要引入它并不困难,可以到真正需要它的时候再对系统进行一下整理,引入命令模式。注意:之前的代码要遵循单一指责原则、代码复用原则,这样才能快速的调整代码结构,改进现有的设计。

2 可以创建空命令(EmptyCommand),降低对空指针条件判断的处理。

3 可以创建智慧命令,直接在命令的执行方法中实现业务逻辑,不委托给执行者。

设计模式-命令模式

原文:http://www.cnblogs.com/fanyang219/p/6404734.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!