使用策略设计模式时如何避免代码重复?求适配设计方案
消除策略模式重复代码的方案及模式选择
一、核心问题分析
你的三个Strategy类存在明显重复:
- 成员变量重复:
Helperclass1和Daoclass是三个类共有的,Helperclass2是StrategyA、B共有的 - 执行流程重复:
execute方法都包含helperclass1.method(obj)和dao.update(updatedObj)的步骤,StrategyA、B还多了helperclass2.method2的步骤
这种场景不需要放弃策略模式,结合模板方法模式就能完美解决代码冗余问题。
二、具体改造方案
1. 抽象基类提取通用逻辑
创建抽象基类AbstractStrategy,把重复的成员变量、固定执行流程放到基类中,仅将变化的部分定义为钩子方法(子类可选择性重写):
abstract class AbstractStrategy implements Strategy { protected final Helperclass1 helperclass1; protected final Daoclass dao; protected final Optional<Helperclass2> helperclass2; // 构造函数注入依赖,避免子类重复声明 public AbstractStrategy(Helperclass1 helperclass1, Daoclass dao, Helperclass2 helperclass2) { this.helperclass1 = helperclass1; this.dao = dao; this.helperclass2 = Optional.ofNullable(helperclass2); } // 模板方法:固定执行流程,用final防止子类篡改 @Override public final void execute(Object obj) { Object updatedObj = helperclass1.method(obj); updatedObj = applyHelper2(updatedObj); updatedObj = customUpdate(updatedObj); dao.update(updatedObj); } // 钩子方法:默认不处理(若helperclass2为空则直接返回原对象),子类无需重写即可复用 protected Object applyHelper2(Object obj) { return helperclass2.map(Helperclass2::method2).orElse(obj); } // 钩子方法:默认返回原对象,仅需要自定义更新的子类重写 protected Object customUpdate(Object obj) { return obj; } }
2. 简化子类实现
每个子类只需要实现自身特有的逻辑,其余复用基类代码:
// StrategyA:仅重写自定义更新逻辑 class StrategyA extends AbstractStrategy { public StrategyA(Helperclass1 helperclass1, Helperclass2 helperclass2, Daoclass dao) { super(helperclass1, dao, helperclass2); } @Override protected Object customUpdate(Object obj) { // 这里实现StrategyA特有的对象更新逻辑 return updatedObj; } } // StrategyB:无需重写任何方法,直接复用基类流程 class StrategyB extends AbstractStrategy { public StrategyB(Helperclass1 helperclass1, Helperclass2 helperclass2, Daoclass dao) { super(helperclass1, dao, helperclass2); } } // StrategyC:仅传入null作为helperclass2,自动跳过该步骤 class StrategyC extends AbstractStrategy { public StrategyC(Helperclass1 helperclass1, Daoclass dao) { super(helperclass1, dao, null); } }
三、模式选择说明
1. 为什么选择模板方法+策略模式?
- 策略模式负责封装不同的业务变体(比如StrategyA的自定义更新),保证灵活性;
- 模板方法模式负责提取固定执行流程,消除重复代码;
- 两者组合是处理“固定流程下的多变体”场景的经典方案,既保留策略的扩展性,又解决冗余问题。
2. 命令模式是否适用?
命令模式核心是将请求封装为对象,适合需要实现命令队列、撤销/重做、日志记录等场景,和你当前“流程变体”的需求匹配度不高,不推荐作为替代方案。
四、额外优化建议
- 用
Optional处理Helperclass2的可选性,避免空指针异常; - 构造函数注入依赖,提高代码的可测试性和扩展性;
- 模板方法
execute用final修饰,确保固定流程不被子类篡改。
内容的提问来源于stack exchange,提问作者Sai
相关产品推荐
相关产品推荐

