简介
"用命令替换函数"是一种面向对象的重构手法。通过将复杂函数封装为独立命令对象,可以解耦操作与参数,支持事务操作、撤销机制等复杂需求,提升代码的可扩展性。
针对的症状(代码坏味道)
- 包含多个参数的长方法
- 需要支持撤销/重做操作
- 方法状态依赖外部上下文
- 需要将操作作为参数传递
用命令替换函数的详细步骤
- 创建命令基类
- 定义执行操作的抽象方法
- 封装公共参数和状态
- 实现具体命令
- 将原函数逻辑迁移到命令类
- 实现参数传递机制
- 重构调用方
- 用命令对象替换函数调用
- 维护命令生命周期
- 支持高级特性
- 添加undo/redo方法
- 实现命令队列支持
示例
重构前代码:
class Calculator {
double calculate(double a, double b, String operator) {
switch (operator) {
case "+":
return a + b;
case "-":
return a - b;
case "*":
return a * b;
case "/":
return a / b;
default:
throw new IllegalArgumentException();
}
}
}
重构步骤:
-
定义命令接口:
interface MathCommand { double execute(double a, double b); } -
实现具体命令类:
class AddCommand implements MathCommand { public double execute(double a, double b) { return a + b; } } // 类似实现SubtractCommand、MultiplyCommand、DivideCommand -
重构计算器类:
class Calculator { double calculate(double a, double b, MathCommand command) { return command.execute(a, b); } }
练习
基础练习题
-
简单操作命令化
// 重构前 class FileManager { void compressFile(String path) { // 压缩文件逻辑 } }
进阶练习题
-
带状态命令改造
// 重构前 class Editor { void applyFont(Text text, Font font, boolean underline) { text.setFont(font); if (underline) text.setUnderline(true); } }
综合拓展练习题
-
支持撤销的命令系统
// 重构前 class DiagramEditor { void moveShape(Shape shape, int dx, int dy) { shape.setX(shape.getX() + dx); shape.setY(shape.getY() + dy); } }
代码审查要点
-
优点:
- 提高代码的可测试性
- 支持复杂操作组合
- 分离操作定义与执行
-
潜在问题:
- 避免过度设计简单操作
- 注意命令对象的生命周期管理
- 合理设计命令接口参数