You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确实现开闭原则(OCP)以避免模板逻辑新增时频繁修改if-else分支

1. 现有if-else实现不符合开闭原则

开闭原则的核心要求是对扩展开放,对修改关闭,你当前每次新增模板都要改动Pg控制器的doProcessing方法,属于修改已上线的稳定逻辑,很容易引入历史功能bug,完全不符合开闭原则的要求。

另外你现有代码还存在明显逻辑问题:你创建了Template1/Template2实例后,没有将其设置到TemplateInfo中,调用templateProduct.calculateTemplate时使用的还是Spring注入的单例TemplateInfo,大概率会触发空指针异常。同时单例TemplateInfo在多线程请求场景下会出现属性覆盖的并发问题,不建议作为单例Bean托管给Spring。


2. Class.forName反射方案不属于最优实践

这个方案确实可以消除if-else分支,但存在多个明显缺陷:

  • 硬编码了类路径前缀ocp.,后续如果包结构调整,所有实例创建逻辑都会失效
  • 反射创建的实例不受Spring生命周期管理,如果你后续需要在Template实现类中注入其他Spring Bean(如DAO、外部服务)将无法实现,可扩展性很差
  • 缺少参数校验机制,传入非法参数会直接抛出类不存在、类型转换错误等运行时异常,排查成本高
  • 反射性能弱于直接获取实例,虽然影响不大但属于不必要的性能损耗

3. 适配Spring环境的最优方案

你已经抽取了TemplateClassification公共接口,结合Spring的Bean管理能力可以零if-else实现完全符合开闭原则的逻辑:

改造步骤

  1. 给所有TemplateClassification实现类添加@Component注解,自定义Bean名称和tempId一一对应:
@Component("template1")
public class Template1 implements TemplateClassification{
    @Override
    public QuesObj processTemplate() {
        return new QuesObj("Hi I am header 1","Hi I am footer 1");
    }
}

@Component("template2")
public class Template2 implements TemplateClassification{
    @Override
    public QuesObj processTemplate() {
        return new QuesObj("Hi I am header 2","Hi I am footer 2");
    }
}
  1. 改造控制器逻辑,直接从Spring上下文获取对应Bean,删除所有if-else:
@RestController
class Pg {
    @Autowired
    ApplicationContext applicationContext;
    @Autowired
    TemplateProduct templateProduct;

    public QuesObj doProcessing(@RequestParam("tempId") int tempId){
        // 校验Bean是否存在,避免非法参数报错
        if(!applicationContext.containsBean("template" + tempId)){
            throw new IllegalArgumentException("非法的模板ID");
        }
        TemplateClassification template = (TemplateClassification) applicationContext.getBean("template" + tempId);
        // 每次请求新建TemplateInfo避免并发问题
        TemplateInfo templateInfo = new TemplateInfo();
        templateInfo.setTemplateClassification(template);
        return templateProduct.calculateTemplate(templateInfo);
    }
}

效果

后续新增模板时,你只需要新建类实现TemplateClassification接口,添加对应@Component注解即可,不需要修改任何原有代码,完全符合开闭原则,同时可以享受到Spring的全部Bean管理能力。


内容的提问来源于stack exchange,提问作者Beginner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 18:06:03