如何根据对象场景设置字段,摒弃布尔标志重构代码?
重构方案推荐
1. 构建者模式(Builder Pattern)
这是处理大型对象按需配置最常用的方案,把每个字段的设置逻辑封装到Builder类的方法中,调用方可以按需调用对应方法,完全替代布尔标志。
示例代码:
首先定义对象的Builder类,把原方法里的业务逻辑迁移到对应的设置方法或build方法中:
public class LargeObject { private Object field1; private Object field2; private Object field3; // 其他字段... private LargeObject(Builder builder) { this.field1 = builder.field1; this.field2 = builder.field2; this.field3 = builder.field3; // 其他字段赋值... } public static class Builder { private Object field1; private Object field2; private Object field3; // 其他字段默认值初始化... // 每个字段对应一个设置方法,封装原有的业务逻辑 public Builder withField1() { // 原flag1对应的业务逻辑,比如计算customValue1 this.field1 = customValue1; return this; } public Builder withField2() { this.field2 = customValue2; return this; } public Builder withField3() { this.field3 = customValue3; return this; } // 如果有通用业务逻辑,放在build里执行 public LargeObject build() { // 原方法中200多行的通用业务逻辑 return new LargeObject(this); } } }
调用的时候直接按需调用对应方法,不需要传布尔标志:
// 只设置field1和field3 LargeObject obj = new LargeObject.Builder() .withField1() .withField3() .build();
优势:可读性极强,符合开闭原则,新增字段只需要加对应的withXxx方法,完全复用原有的200多行业务逻辑,不会产生重复代码。
2. 配置项枚举+批量应用
如果字段的配置逻辑是固定的,可以把每个字段的设置逻辑封装成枚举项,调用时传入需要启用的枚举集合,循环执行配置逻辑。
示例代码:
public enum ObjectConfig { FIELD1 { @Override public void apply(LargeObject obj) { // 原flag1对应的业务逻辑 obj.setField1(customValue1); } }, FIELD2 { @Override public void apply(LargeObject obj) { obj.setField2(customValue2); } }, FIELD3 { @Override public void apply(LargeObject obj) { obj.setField3(customValue3); } }; public abstract void apply(LargeObject obj); // 批量应用配置 public static void applyConfigs(LargeObject obj, ObjectConfig... configs) { // 先执行原方法中的200多行通用业务逻辑 // ... for (ObjectConfig config : configs) { config.apply(obj); } } }
调用时直接传入需要的配置项:
LargeObject obj = new LargeObject(); ObjectConfig.applyConfigs(obj, ObjectConfig.FIELD1, ObjectConfig.FIELD3);
优势:把配置逻辑集中管理,新增字段只需要加枚举项,调用方清晰知道可选的配置项,同样复用原有的通用业务逻辑。
3. 功能接口组合(替代Supplier的更灵活方案)
定义一个函数式接口,用来封装字段的设置逻辑,调用时传入需要的处理器列表,逐个执行。这种方案比Supplier更灵活,因为可以直接操作对象,不需要返回值。
示例代码:
首先定义函数式接口:
@FunctionalInterface public interface ObjectProcessor { void process(LargeObject obj); }
然后把每个字段的设置逻辑做成处理器实例:
// 可以把这些处理器放在工具类或内部类中 public static final ObjectProcessor PROCESS_FIELD1 = obj -> { // 原flag1对应的业务逻辑 obj.setField1(customValue1); }; public static final ObjectProcessor PROCESS_FIELD2 = obj -> { obj.setField2(customValue2); }; public static final ObjectProcessor PROCESS_FIELD3 = obj -> { obj.setField3(customValue3); };
然后编写通用的构建方法:
public static LargeObject createObject(List<ObjectProcessor> processors) { LargeObject obj = new LargeObject(); // 执行原方法中的200多行通用业务逻辑 // ... for (ObjectProcessor processor : processors) { processor.process(obj); } return obj; }
调用时传入需要的处理器:
LargeObject obj = createObject(Arrays.asList(PROCESS_FIELD1, PROCESS_FIELD3));
优势:高度灵活,甚至可以动态生成处理器(比如根据业务逻辑动态创建),完全复用通用代码,没有重复。
内容的提问来源于stack exchange,提问作者Theodor3699
相关产品推荐
相关产品推荐

