Java计算器如何规避if-else/switch链并遵循开闭原则
符合SOLID开闭原则的计算器实现方案
要消除switch语句并遵循开闭原则,核心思路是将运算类型与具体实现解耦,让新增运算时无需修改原有核心代码。下面给出具体的Java实现方案:
1. 定义统一的运算接口
首先,让所有运算实现同一个接口,包含计算逻辑和描述文本的方法(满足打印需求):
public interface Operation { // 执行计算 float calculate(float currentValue, float newValue); // 返回运算描述(用于打印) String getDescription(float currentValue, float newValue); }
2. 实现具体运算类
为每个运算单独创建类,实现Operation接口,比如加法:
public class AdditionOperation implements Operation { @Override public float calculate(float currentValue, float newValue) { return currentValue + newValue; } @Override public String getDescription(float currentValue, float newValue) { return String.format("%.1f added to %.1f", currentValue, newValue); } }
减法、乘法、除法以此类推,后续新增模运算时,只需要新增ModuloOperation类即可,完全不影响现有代码。
3. 改造运算枚举,绑定具体实现
把OperationType枚举改造为持有对应运算实例,通过枚举直接获取运算实现,彻底抛弃switch:
public enum OperationType { ADD(new AdditionOperation()), SUBTRACT(new SubtractionOperation()), MULTIPLY(new MultiplicationOperation()), DIVIDE(new DivisionOperation()); // 新增模运算时,仅需添加这一行:MODULO(new ModuloOperation()) private final Operation operation; OperationType(Operation operation) { this.operation = operation; } public Operation getOperation() { return operation; } }
4. 重构Calculator类,移除switch逻辑
修改execute方法,直接通过枚举获取运算实例执行计算,同时记录运算过程用于打印:
import java.util.ArrayList; import java.util.List; public class Calculator { private float currentValue; private final List<OperationRecord> operationRecords = new ArrayList<>(); // 内部类存储运算记录,方便后续打印 private static class OperationRecord { private final Operation operation; private final float currentValue; private final float newValue; public OperationRecord(Operation operation, float currentValue, float newValue) { this.operation = operation; this.currentValue = currentValue; this.newValue = newValue; } public String getDescription() { return operation.getDescription(currentValue, newValue); } } public Calculator(float initialValue) { this.currentValue = initialValue; } public Calculator execute(OperationType operationType, float newValue) { Operation operation = operationType.getOperation(); float result = operation.calculate(currentValue, newValue); // 记录运算过程 operationRecords.add(new OperationRecord(operation, currentValue, newValue)); currentValue = result; return this; } // 给打印类提供只读的记录列表 public List<OperationRecord> getOperationRecords() { return new ArrayList<>(operationRecords); } public float getCurrentValue() { return currentValue; } }
5. 适配PrintHandler类
调整打印逻辑,读取运算记录并输出:
public class PrintHandler { private final Calculator calculator; public PrintHandler(Calculator calculator) { this.calculator = calculator; } public void printResults() { calculator.getOperationRecords().forEach(record -> System.out.println(record.getDescription())); System.out.println("-----------"); System.out.printf("Total: %.1f%n", calculator.getCurrentValue()); } }
效果验证
原App类的代码完全不用修改,运行后输出和之前一致。当需要新增模运算时:
- 创建
ModuloOperation实现Operation接口 - 在
OperationType枚举中添加MODULO(new ModuloOperation())
无需修改Calculator、PrintHandler等任何现有核心代码,完美符合开闭原则。
方案优势
- 彻底消除了
switch/if-else语句,代码更简洁易维护 - 新增运算仅需扩展类和枚举项,完全遵循对扩展开放、对修改关闭的原则
- 运算逻辑与核心计算器逻辑解耦,每个运算类职责单一(符合单一职责原则)
内容的提问来源于stack exchange,提问作者Jwok
相关产品推荐
相关产品推荐

