if-else膨胀难维护的本质是职责错位,即策略选择与执行混杂;应通过工厂+策略模式解耦,定义统一接口、实现具体策略、用预注册Map工厂封装创建逻辑,使主流程简化为一行调用。

为什么 if\_else 膨胀后难维护,不是逻辑问题而是职责错位
当一个函数里出现 5 个以上 if-else 分支,且每个分支都在做「不同类型的处理」(比如不同支付方式、不同导出格式、不同审核规则),问题本质不是条件多,而是把「策略选择」和「策略执行」混在了一起。工厂模式负责解耦对象创建,策略模式负责解耦算法行为——两者配合,能把 if-else 从主流程里彻底摘出去。
用工厂 + 策略组合替换 if\_else 的三步实操
以「订单导出」为例:支持 Excel、PDF、CSV 三种格式,原逻辑类似:
if (type.equals("excel")) {
new ExcelExporter().export(orderList);
} else if (type.equals("pdf")) {
new PdfExporter().export(orderList);
} else if (type.equals("csv")) {
new CsvExporter().export(orderList);
}
替换成策略+工厂的关键动作:
-
定义统一策略接口:
Exporter,含export(List<order>)</order>方法 -
为每种类型实现策略类:如
ExcelExporter、PdfExporter,都实现Exporter -
用工厂封装创建逻辑:写一个
ExporterFactory,内部用Map<string exporter></string>预注册所有策略实例(或按需 new);调用方只传type,工厂返回对应Exporter
之后主流程就只剩一行:exporterFactory.getExporter(type).export(orderList)。新增格式只需加实现类 + 注册进工厂,不碰原有逻辑。
工厂注册策略时容易踩的坑
常见错误是把工厂写成静态方法 + 大量 if-else,等于换汤不换药:
public static Exporter get(String type) {
if ("excel".equals(type)) return new ExcelExporter();
if ("pdf".equals(type)) return new PdfExporter();
// ……又来一遍 if-else
}
正确做法是避免运行时判断:
- 启动时用
Map预注册,key 是类型标识(如"excel"),value 是策略实例(推荐单例) - 注册来源可以是 Spring 的
@Bean+@Qualifier,或手写static块初始化 - 如果策略需传参(如
PdfExporter(String templatePath)),工厂里别硬编码路径,改用配置项或构造参数注入 - 务必检查
getExporter(type)返回null的情况——建议抛IllegalArgumentException并带明确定义的错误码,而不是静默失败
策略类之间共享逻辑怎么抽?别动 factory,动 strategy
多个策略有共用代码(比如都需校验权限、都需记录日志),不要塞进工厂,也不要在每个策略里重复写。两种安全做法:
- 写一个
BaseExporter抽象类,把公共逻辑放templateMethod()里,子类只覆写doExport() - 用组合:策略类持有一个
ExportHelper,把校验、日志等作为独立服务注入,保持策略本身无状态
注意:别为了“复用”把策略类变成继承树过深,两层(抽象基类 + 具体实现)足够。超过三层,往往说明策略分类维度本身有问题。
真正难的从来不是写策略或工厂,而是厘清哪些该变(策略内容)、哪些不该变(策略选择机制)。一旦把 if-else 拆成可插拔的策略实例,后续加新分支就只是增文件、改配置,而不是翻旧代码、怕改崩。

















