`

设计模式之命令模式

阅读更多

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

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

  命令模式包含四种角色:

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

  命令接口:命令式一个接口,规定了用来封装“请求”的若干个方法,比如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();
    }
}
复制代码

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

分享到:
评论

相关推荐

    设计模式之命令模式案例代码

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在本文中,我们将深入探讨命令模式的原理、结构和实际应用,并...

    深入浅出设计模式之命令模式

    ### 深入浅出设计模式之命令模式 #### 前言 设计模式作为软件工程中的重要组成部分,为开发者提供了解决常见问题的有效途径。在众多设计模式中,命令模式是一种行为型设计模式,它把请求封装成对象,以便使用不同的...

    [行为模式] head first 设计模式之命令模式(Command)

    【行为模式】Head First 设计模式之命令模式(Command) 命令模式是一种行为设计模式,它将请求封装为一个对象,从而使我们能支持可撤销的操作、参数化对象以及将请求排队等高级操作。在Head First的设计模式书中,...

    java设计模式之命令模式

    **Java设计模式之命令模式详解** 命令模式是一种行为设计模式,它将请求封装为一个对象,使得你可以使用不同的请求、队列或者日志请求,也可以支持可撤销的操作。在Java编程中,命令模式广泛应用于解耦请求的发送者...

    设计模式之命令模式源码示例

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式广泛应用在各种场景中,以提高代码的灵活...

    设计模式之命令模式(Command)

    命令模式是一种行为设计模式,它的主要目的是将请求者与接收者解耦,使得请求的发起者无需知道哪个对象会执行这个请求,同时也让系统更容易扩展。这种模式在软件工程中广泛应用,特别是在事件驱动和分布式系统中。 ...

    Java设计模式之命令模式/Java函数式编程 笔记

    Java设计模式之命令模式/Java函数式编程 笔记

    设计模式之命令模式(Command Pattern)

    命令模式是一种行为设计模式,它将请求封装成独立的对象,使得可以使用不同的请求、队列请求、记录请求历史以及支持可撤销的操作。这种模式在软件工程中被广泛应用,尤其是在需要解耦请求发起者和接收者时,提高了...

    23钟设计模式之命令模式

    命令模式是一种行为设计模式,它的主要目的是将请求封装为一个对象,以便支持可撤销的操作、参数化不同命令以及将命令的执行与请求者解耦。在23种经典设计模式中,命令模式因其灵活性和实用性而被广泛使用。 在命令...

    设计模式之命令模式详解(内附有例子,无源码)

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在软件工程中,这种模式常用于降低系统之间的耦合度,提高灵活性...

    设计模式之命令模式Java实现

    命令模式是一种行为设计模式,它将请求封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。在Java中实现命令模式,我们可以按照以下步骤进行: 1. **定义...

    c++-设计模式之命令模式(Command Pattern)

    命令模式(Command Pattern)是一种行为型设计模式,它将请求封装为对象,从而使您可以使用不同的请求、队列请求或日志请求,并支持可撤销操作。命令模式通常用于实现操作的解耦,使得发送者和接收者之间不直接关联...

Global site tag (gtag.js) - Google Analytics