java实现命令模式

java实现命令模式

命令模式属于行为设计模式,是Gof设计模式正式列表之一。简言之,命令模式在一个对象中封装执行给定动作的所有数据,包括要执行方法,方法参数以及方法所属对象。通过该模式可以把消费者和命令对象生产者进行解耦,因此也称为生产者-消费者模式。

本文我们学习在java如何实现命令模式,分别通过面向对象和面向函数两种方法,并了解哪些用例可能有用。

面向对象实现

经典实现中,命令模式需要实现四个组件:命令(Command)、接收者(Receiver)、执行器(Invoker)以及客户端(Client)。为了更好理解模式如何工作以及每个组件对应角色,我们通过具体示例进行说明。

假设我们想开发一个文本文件应用程序,需要实现所有执行文本文件相关操作功能,如打开、写、保存等。

所以我们需要把应用分解为上述四个组件。

命令类

命令对象作用是存储执行动作所需的的所有信息,包括要执行的方法、方法参数以及实现方法的对象(接收者)。为了更准确理解命令对象,我们开始开发简单命令接口及其两个实现:

@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实例)。

接收者类

接收者是执行一组内聚操作的对象,是执行实际动作的组件,通过调用命令的excute方法。因此我们定义接收类,是对文本文件对象的建模:

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();
    }
}

TextFileOperationExecutor可是抽象层,对命令对象和消费者进行解耦并调用封装在TextFileOperation 命令对象的方法。
同时也存储命令对象至List中,当然这不是命令模式实现必须的,仅仅为了执行过程中增加一些额外的控制。

客户端类

客户端对象是控制命令执行过程,通过指定什么命令要执行,在那个阶段处理执行。因此,为了遵循模式的正式定义,我们定义客户端类,使用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"))));
}

面向函数实现

到目前为止,我们使用面向对象方法实现命令模式,这非常好。从java8开始,我们可以使用面向函数方法,基于lambda表达式和方法引用,是代码更小、更简洁,避免模版代码。

使用Lambda 表达式

TextFileOperation 接口是函数式接口,我们可以给执行类以lambda形式传递命令对象,则无需显示地创建TextFileOperation 实例:

TextFileOperationExecutor textFileOperationExecutor = new TextFileOperationExecutor();
textFileOperationExecutor.executeOperation(() -> "Opening file file1.txt");
textFileOperationExecutor.executeOperation(() -> "Saving file file1.txt");

现在实现看起来更加精简和简洁,因为我们减少了样板代码的数量。即便如此,问题仍然存在:与面向对象的方法相比,这种方法更好吗? 没有绝对的答案,如果假设在大多数情况下,更紧凑的代码意味着更好的代码,那么事实确实如此。根据经验,我们应该根据每个情况确定何时使用lambda表达式。

使用方法引用

类似的,我们也可以使用方法引用给执行器传递命令对象:

TextFileOperationExecutor textFileOperationExecutor
 = new TextFileOperationExecutor();
TextFile textFile = new TextFile("file1.txt");
textFileOperationExecutor.executeOperation(textFile::open);
textFileOperationExecutor.executeOperation(textFile::save);

在本例中,实现比使用lambdas的实现稍微复杂点,因为仍然需要创建TextFile实例。

总结

本文我们学习了命令模式的关键概念,以及如何在java通过面向对象和面向函数进行实现。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值