注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

北漂的小羊

Java编程,开发者,程序员,软件开发,编程,代码。新浪微博号:IT国子监

 
 
 

日志

 
 
关于我

在这里是面向程序员的高品质IT技术学习社区,是程序员学习成长的地方。让我们更好地用技术改变世界。请关注新浪微博号: IT国子监(http://weibo.com/itguozijian)

网易考拉推荐

天涯草:设计模式之命令模式  

2013-04-16 21:17:48|  分类: 设计模式 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 在许多设计中,经常设计一个对象请求另一个对象执行某一个操作。如果请求者无法或者不希望直接和被请求者打交道,即请求对象无法或者不希望含有被请求者的引用,那么可以使用命令模式。命令模式里称提出请求的对象为请求者,被请求者的对象为接收者。在命令模式中,当一个对象请求另一个对象调用其方法时,不和被请求者直接打交道,而是把这种“请求”封装到一个“命令”对象中,封装的手段将“请求”封装到“命令”对象的一个方法中。命令模式的核心就是使用命令对象来封装方法调用。

 GOF 在《设计模式》一书中阐述其意图:“将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。”这里所谓的“不同的请求”也既意味着请求可能发生的变化,是一个可能扩展的功能点。

  例如,在军队作战时,指挥官要命令三连偷袭敌人。但是指挥官这时无法或者不希望和三连直接取得联系,那么指挥官可以发出一个命令,把该命令的执行者设置为三连。这样指挥官只要和命令打交道。

  命令模式包含四种角色:

  接收者:接收者是一个类的实例,该实例负责执行与请求相关的操作。

  命令接口:命令式一个接口,规定了用来封装“请求”的若干个方法,比如execute()、undo()等方法。

  具体命令:具体命令式实现了命令接口的类的实例,包含命令接口的方法。并且包含接受者的引用,指明那个对象去执行该命令。

  请求者:请求者是包含命令接口变量类的实例,该接口变量可以存放任何具体命令的引用。请求者负责调用具体命令,让具体命令执行那些封装了的请求方法。

如何使用?
具体的Command模式代码各式各样,因为如何封装命令,不同系统,有不同的做法.下面事例是将命令封装在一个Collection的List中,任何对象一旦加入List中,实际上装入了一个封闭的黑盒中,对象的特性消失了,只有取出时,才有可能模糊的分辨出:

下面看军队作战的例子:

  1.命令接收者:

 1.命令接收者:

1 package com.command;
2 //命令接收者、执行者
3 public class CompanyArmy {
4     public void sneakAttack(){
5         System.out.println("我们知道如何袭击敌人,保证完成任务");
6     }
7 }

  2.命令接口:

1 package com.command;
2 //命令接口
3 public interface Command {
4     void execute();
5 }

  3.具体命令:

 1 package com.command;
 2 //具体命令
 3 public class ConcreteCommand implements Command{
 4     CompanyArmy army;  //含有接收者的引用
 5     public ConcreteCommand(CompanyArmy army) {
 6         this.army = army;
 7     }
 8     public void execute() {   //封装着指挥官的请求
 9         army.sneakAttack();   //偷袭敌人
10     }
11 }

  4.请求者:

 1 package com.command;
 2 //请求者,也就是命令发送者
 3 public class ArmySuperior {
 4     Command command;     //存放具体命令的引用
 5     public void setCommand(Command command){
 6         this.command = command;
 7     }
 8     public void startExecuteCommand(){
 9         command.execute();
10     }
11 }

  命令模式所需要的四个角色已经建立好了,下面测试一下:

 1 package com.command;
 2 
 3 public class Application {
 4     public static void main(String[] args) {
 5         CompanyArmy army = new CompanyArmy();   //创建命令接收者
 6         Command command = new ConcreteCommand(army);//创建一个具体命令并且指定接收者
 7         ArmySuperior superior = new ArmySuperior();    //创建命令请求者
 8         superior.setCommand(command);   //给请求者设置一个具体命令
 9         superior.startExecuteCommand();   //开始执行命令
10     }
11 }

  这样就可以实现指挥官不直接和命令执行者,只需要发送一个命令,该命令就会找到指定的执行者去执行。这样大大降低了程序的耦合度。另外还有一个好处就是,要想发送另外一个命令只要再创建一个具体的命令即可,不需要修改其他代码,增强了程序的扩展性。

  使用命令模式还有一个好处,就是可以撤销所执行的操作。也就是请求者发送一个请求,接收者执行后,还可以撤销该操作。以下使用一个简单的例子说明怎样在具体的命令中实现undo()方法。问题如下:

  请求者请求在硬盘建立一个目录,请求成功后海可以撤销请求。这就要求接收者不仅可以在硬盘上建立目录,海可以删除上一次建立的目录。

  1接收者:要包含两个方法,建立目录和删除目录

 1 package com.command1;
 2 import java.io.File;
 3 //命令接收者
 4 public class MakeDir {
 5     //创建目录
 6     public void createDir(String name){
 7         File dir = new File(name);
 8         dir.mkdir();
 9     }
10     //删除目录
11     public void deleteDir(String name){
12         File dir = new File(name);
13         dir.delete();
14     }
15 }

 

  2.命令接口

1 package com.command1;
2 //包含撤销的命令接口
3 public interface Command {
4     void execute(String name);
5     void undo();
6 }

 

  3.具体命令

 1 package com.command1;
 2 import java.util.ArrayList;
 3 //具体命令
 4 public class ConcreteCommand implements Command {
 5     ArrayList<String> dirNameList;
 6     MakeDir makeDir;
 7     public ConcreteCommand(MakeDir makeDir) {
 8         dirNameList = new ArrayList<String>();
 9         this.makeDir = makeDir;
10     }
11     public void execute(String name) {
12         makeDir.createDir(name);
13         dirNameList.add(name);
14     }
15     public void undo() {
16         if(dirNameList.size()>0){
17             makeDir.deleteDir(dirNameList.get(dirNameList.size()-1));
18             dirNameList.remove(dirNameList.size()-1);
19         }else{
20             System.out.println("没有需要撤销的操作!");
21         }
22     }
23 }

 

  4.请求者

 1 package com.command1;
 2 //请求者
 3 public class RequestMakeDir {
 4     Command command;
 5     public void setCommand(Command command) {
 6         this.command = command;
 7     }
 8     public void startExecuteCommand(String name){
 9         command.execute(name);
10     }
11     public void undoCommand(){
12         command.undo();
13     }
14 }

  包含撤销的命令模式的四个角色创建好了,下面写一个测试类:

package com.command1;

public class Application {
    public static void main(String[] args) {
        MakeDir makeDir = new MakeDir();  //创建接收者
        Command command = new ConcreteCommand(makeDir);//创建具体命令并且指定接收者
        RequestMakeDir request = new RequestMakeDir(); //创建请求者
        request.setCommand(command);   //设置命令
        request.startExecuteCommand("haha");  //创建目录
        request.startExecuteCommand("hahaa");
        request.undoCommand();  //撤销
        request.undoCommand();
    }
}

  这样就可以创建目录和撤销操作了。

在众多的设计模式中,Command模式是很简单也很优雅的一种设计模式。Command模式它封装的是命令,把命令发出者的责任和命令执行者的责任分开。
  评论这张
 
阅读(398)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016