You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

简易终端命令解析器的命令模式设计问题求助

解决方案:引入命令工厂模式优化命令解析流程

针对你遇到的命令模式下参数延迟传递、冗余参数的问题,我们可以通过**命令工厂(Command Factory)**来重构现有逻辑,既保持命令模式的扩展性,又避免冗余参数和提前初始化命令对象的问题。

核心思路

  1. 将命令的创建逻辑从CommandExecutionController中剥离,交给专门的工厂类处理
  2. 每个命令对应一个工厂,工厂负责校验参数并创建命令实例(此时参数已经解析完成)
  3. 保持CommandInterface的纯净性,execute()方法不带冗余参数
  4. 注册和存储的是工厂而非命令类,解决参数延迟传递的问题

代码重构实现

1. 重构基础接口

首先定义纯净的命令接口和工厂接口:

// 命令接口:仅负责执行逻辑,无冗余参数
public interface CommandInterface {
    String execute();
}

// 命令工厂接口:负责参数校验和命令实例创建
public interface CommandFactory {
    CommandInterface create(FileSystemModel fs, String[] args) throws IllegalArgumentException;
}

2. 修改命令执行控制器

让控制器存储和管理工厂实例,而非命令类:

import java.util.HashMap;
import java.util.Map;

public class CommandExecutionController {
    private final Map<String, CommandFactory> commandFactories;
    private final FileSystemModel fileSystemModel;

    public CommandExecutionController(final FileSystemModel fileSystemModel) {
        this.commandFactories = new HashMap<>();
        this.fileSystemModel = fileSystemModel;
    }

    public void register(final String commandName, CommandFactory factory) {
        commandFactories.put(commandName, factory);
    }

    public CommandInterface getDispatchedCommand(final String commandName, final String... arguments) {
        CommandFactory factory = commandFactories.get(commandName);
        if (factory == null) {
            throw new IllegalArgumentException("Command NOT found: " + commandName);
        }
        return factory.create(fileSystemModel, arguments);
    }
}

3. 实现具体命令与工厂

以cd和help命令为例,命令类仅接收必要参数,工厂负责参数校验:

// CdCommand:仅接收FileSystem和路径参数,无冗余
public class CdCommand implements CommandInterface {
    private final String path;
    private final FileSystemModel fileSystemModel;

    public CdCommand(final FileSystemModel fileSystemModel, final String path) {
        this.path = path;
        this.fileSystemModel = fileSystemModel;
    }

    @Override
    public String execute() {
        return fileSystemModel.cd(path);
    }
}

// CdCommand工厂:校验参数数量,创建命令实例
public class CdCommandFactory implements CommandFactory {
    @Override
    public CommandInterface create(FileSystemModel fs, String[] args) {
        if (args.length != 1) {
            throw new IllegalArgumentException("cd command requires exactly 1 argument");
        }
        return new CdCommand(fs, args[0]);
    }
}

// HelpCommand:仅接收FileSystem,无参数
public class HelpCommand implements CommandInterface {
    private final FileSystemModel fileSystemModel;

    public HelpCommand(final FileSystemModel fileSystemModel) {
        this.fileSystemModel = fileSystemModel;
    }

    @Override
    public String execute() {
        return "Available commands:\n- cd [path]: Change directory\n- mv [source] [dest]: Move file\n- help: Show help info";
    }
}

// HelpCommand工厂:校验无参数,创建命令实例
public class HelpCommandFactory implements CommandFactory {
    @Override
    public CommandInterface create(FileSystemModel fs, String[] args) {
        if (args.length != 0) {
            throw new IllegalArgumentException("help command takes no arguments");
        }
        return new HelpCommand(fs);
    }
}

4. 注册与调用命令

注册时绑定命令名和对应工厂,调用时直接传递解析后的参数数组:

// 注册命令示例
FileSystemModel fs = new FileSystemModel();
CommandExecutionController controller = new CommandExecutionController(fs);
controller.register("cd", new CdCommandFactory());
controller.register("help", new HelpCommandFactory());
controller.register("mv", new MvCommandFactory()); // 同理实现mv的工厂和命令

// 调用逻辑优化(修复原代码中参数join的错误)
text = text.trim();
final String[] commandParts = text.split("\\s+");
if (commandParts.length == 0) {
    return "Empty command";
}

try {
    final CommandInterface command = controller.getDispatchedCommand(
        commandParts[0],
        Arrays.copyOfRange(commandParts, 1, commandParts.length)
    );
    return command.execute();
} catch (IllegalArgumentException e) {
    return e.getMessage();
}

方案优势

  • 无冗余参数:每个命令的构造函数仅接收必要参数,避免String...带来的冗余和不安全
  • 扩展性强:新增命令只需实现CommandInterface和CommandFactory,注册即可,无需修改核心控制器逻辑
  • 职责分离:工厂负责参数校验和实例创建,命令类专注于执行逻辑,符合单一职责原则
  • 避免提前初始化:命令实例在参数解析完成后才由工厂创建,完全适配解析流程

简化优化:用Lambda替代简单工厂

对于逻辑简单的命令,可以直接用Lambda表达式注册,无需单独编写工厂类:

controller.register("help", (fs, args) -> {
    if (args.length != 0) {
        throw new IllegalArgumentException("help takes no arguments");
    }
    return new HelpCommand(fs);
});

内容的提问来源于stack exchange,提问作者Celine

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:55:38