Java中如何从命令模式的Command类中退出以停止应用运行?
方案1:修改Command接口返回值(推荐,可维护性最高)
你可以把Command的void返回值改为boolean或者自定义状态枚举,Controller层根据返回结果判断是否终止循环,这种方式逻辑最直观,没有额外开销,也完全不影响日志输出和单元测试。
- 调整Command接口定义:
public interface Command { // 返回true代表需要终止Controller的输入循环,false代表继续执行 boolean execute(Model model); }
- 修改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实现很多,不想全部修改返回值,可以用专用的自定义异常作为终止信号,这种异常只做流程控制用,不需要携带异常信息和栈轨迹,性能开销极低。
- 定义终止信号异常:
// 关闭栈轨迹采集,降低开销 public class AppExitSignal extends RuntimeException { public AppExitSignal() { super(null, null, false, false); } }
- 需要退出的Command内部直接抛出该异常:
@Override public void do(Model m) { // 退出逻辑 throw new AppExitSignal(); }
- 在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
相关产品推荐
相关产品推荐

