Java设计模式-命令模式Command

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

在这里插入图片描述

介绍

  1. 命令模式Command Pattern在软件设计中我们经常需要向某些对象发送请求但是并不知道请求的接收 者是谁也不知道被请求的操作是哪个 我们只需在程序运行时指定具体的请求接收者即可此时可以使用命令模式来进行设计
  2. 命名模式使得请求发送者与请求接收者消除彼此之间的耦合让对象之间的调用关系更加灵活实现解耦。
  3. 在命名模式中会将一个请求封装为一个对象以便使用不同参数来表示不同的请求(即命名)同时命令模式 也支持可撤销的操作。
  4. 通俗易懂的理解将军发布命令士兵去执行。其中有几个角色将军命令发布者、士兵命令的具体执 行者、命令(连接将军和士兵)。 Invoker 是调用者将军Receiver 是被调用者士兵MyCommand 是命令实现了 Command 接口持 有接收对象

原理类图

在这里插入图片描述

  1. Invoker 是调用者角色
  2. Command: 是命令角色需要执行的所有命令都在这里可以是接口或抽象类
  3. Receiver: 接受者角色知道如何实施和执行一个请求相关的操作
  4. ConcreteCommand: 将一个接受者对象与一个动作绑定调用接受者相应的操作实现 execute

实战案例

假设我们要开发一个文本文件应用程序。在这种情况下我们应该实现执行某些与文本文件相关的操作所需的所有功能例如打开写入保存文本文件等。

因此我们应该将应用程序分解为上述四个组件。

命令类

命令是一个对象其作用是存储执行操作所需的所有信息包括要调用的方法、方法参数和实现该方法的对象称为接收器。

为了更准确地了解命令对象的工作原理让我们开始开发一个简单的命令层它只包含一个接口和两个实现

@FunctionalInterface
public interface TextFileOperation {
    String execute();
}

public class OpenTextFileOperation implements TextFileOperation{
    private final TextFile textFile;
    
    public OpenTextFileOperation(TextFile textFile) {
        this.textFile = textFile;
    }
    
    @Override
    public String execute() {
        return textFile.open();
    }
}

public class SaveTextFileOperation implements TextFileOperation {
	private final TextFile textFile;
    
    public SaveTextFileOperation(TextFile textFile) {
        this.textFile = textFile;
    }
    
    @Override
    public String execute() {
        return textFile.save();
    }
}

在这种情况下TextFileOperation接口定义了命令对象的API两个实现OpenTextFileOperation和SaveTextFileOperation执行具体操作。 前者打开文本文件后者保存文本文件。

可以清楚地看到命令对象的功能TextFileOperation 命令封装了打开和保存文本文件所需的所有信息包括接收器对象、要调用的方法和参数在这种情况下不需要参数但可以。

值得强调的是执行文件操作的组件是接收器TextFile 实例。

接收器类

接收方是执行一组内聚操作的对象。它是在调用命令的 execute 方法时执行实际操作的组件。

在这种情况下我们需要定义一个接收器类其作用是建模 TextFile 对象

public class TextFile {
    private final String name;
    
    public TextFile(String name) {
        this.name = name;
    }
    
    public String open() {
        return "Opening file " + name;
    }
    
    public String read() {  
        return "Reading file " + name;
    }
    
    public String write() {  
        return "Writing to file " + name;
    }
    
    public String save() {  
        return "Saving file " + name;
    }
    
    public String copy() {  
        return "Copying file " + name;
    }
    
    public String paste() {  
        return "Pasting file " + name;
    }
}

调用程序类

调用程序是一个对象它知道如何执行给定的命令但不知道命令是如何实现的。它只知道命令的界面。

在某些情况下除了执行命令之外调用程序还会存储和排队命令。这对于实现一些附加功能非常有用例如宏录制或撤消和重做功能。

在我们的示例中很明显必须有一个额外的组件负责调用命令对象并通过命令的 execute 方法执行它们。这正是调用程序类发挥作用的地方。

让我们看一下调用程序的基本实现

public class TextFileOperationExecutor {
    
    private final List<TextFileOperation> textFileOperations
     = new ArrayList<>();
    
    public String executeOperation(TextFileOperation textFileOperation) {
        textFileOperations.add(textFileOperation);
        return textFileOperation.execute();
    }
}

类只是一个薄的抽象层它将命令对象与其使用者分离并调用封装在 TextFileOperation 命令对象中的方法。

在这种情况下该类还将命令对象存储在列表中。当然这在模式实现中不是强制性的除非我们需要为操作的执行过程添加一些进一步的控制。

客户端类

客户端是一个对象它通过指定要执行的命令以及在进程的哪些阶段执行命令来控制命令执行过程。

因此如果我们想与模式的正式定义正统我们必须使用典型的 main 方法创建一个客户端类

public static void main(String[] args) {
    TextFileOperationExecutor textFileOperationExecutor
      = new TextFileOperationExecutor();
    textFileOperationExecutor.executeOperation(
      new OpenTextFileOperation(new TextFile("file1.txt"))));
    textFileOperationExecutor.executeOperation(
      new SaveTextFileOperation(new TextFile("file2.txt"))));
}
  • 输出结果
    在这里插入图片描述
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Java