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

Java中如何从命令模式的Command类中退出以停止应用运行?

方案1:修改Command接口返回值(推荐,可维护性最高)

你可以把Command的void返回值改为boolean或者自定义状态枚举,Controller层根据返回结果判断是否终止循环,这种方式逻辑最直观,没有额外开销,也完全不影响日志输出和单元测试。

  1. 调整Command接口定义:
public interface Command {
    // 返回true代表需要终止Controller的输入循环,false代表继续执行
    boolean execute(Model model);
}
  1. 修改Controller的go方法逻辑:
public void go(Model m) {
    while (scan.hasNext()) {
        String input = scan.next();
        Command command = this.commandMap.get(input);
        // 补充空值判断,避免未知输入抛空指针
        if (command != null && command.execute(m)) {
            break;
        }
    }
    // 循环自然退出,所有缓冲区的日志都会正常flush
}

如果后续需要扩展更多执行状态(比如执行失败重试、跳转其他命令等),可以把返回值替换为自定义枚举,扩展性更强。

方案2:抛自定义终止信号异常(适合不想改动现有Command签名的场景)

如果你的现有Command实现很多,不想全部修改返回值,可以用专用的自定义异常作为终止信号,这种异常只做流程控制用,不需要携带异常信息和栈轨迹,性能开销极低。

  1. 定义终止信号异常:
// 关闭栈轨迹采集,降低开销
public class AppExitSignal extends RuntimeException {
    public AppExitSignal() {
        super(null, null, false, false);
    }
}
  1. 需要退出的Command内部直接抛出该异常:
@Override
public void do(Model m) {
    // 退出逻辑
    throw new AppExitSignal();
}
  1. 在Controller的go方法中捕获该异常终止循环:
public void go(Model m) {
    try {
        while (scan.hasNext()) {
            String input = scan.next();
            Command command = this.commandMap.get(input);
            if (command != null) {
                command.do(m);
            }
        }
    } catch (AppExitSignal ignore) {
        // 捕获到终止信号直接退出循环,不需要额外处理
    }
}

注意:不建议用System.exit(0),它会直接终止JVM进程,Appendable缓冲区中未flush的内容会丢失,也会直接中断JUnit测试进程,完全不符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 20:24:02