欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式之命令模式

程序员文章站 2022-05-03 23:18:46
...

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

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

  命令模式包含四种角色:

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

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

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

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

下面看军队作战的例子:

  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();
    }
}
设计模式之命令模式
            
    
    博客分类: 设计模式 命令模式

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

相关标签: 命令模式