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

如何重构控制器中违背开闭原则的switch分支代码?

重构方案:策略模式+枚举绑定

这确实是个典型的违反开闭原则的场景——每次新增Subject类型都要修改原有switch代码,维护起来越往后越麻烦。咱们可以用策略模式+枚举绑定的方式重构,完美符合开闭原则:新增类型时只需要扩展代码,不用修改原有逻辑。

步骤1:定义处理逻辑的统一接口

首先创建一个通用的处理接口,让所有Subject对应的业务逻辑都实现这个接口,保证调用方式一致:

public interface SubjectHandler {
    void handle(JSONObject data);
}

步骤2:让枚举直接绑定对应处理逻辑

把原来switch分支里的每个业务逻辑,直接绑定到对应的枚举常量上。这样枚举本身就成为了策略的容器,逻辑和枚举值一一对应:

public enum Subject {
    // 每个枚举常量直接绑定对应的Lambda处理逻辑
    SEND_VERIFY(data -> {
        sendFoo1(data.getString("foo1_1"), data.getString("foo1_2"));
    }),
    DO_FOO2(data -> {
        foo2(data.getInt("foo2_b"), data.getInt("foo2_cc"));
    }),
    DO_FOO3(data -> {
        doFoo3For(data.getString("foo3"));
    });

    private final SubjectHandler handler;

    // 枚举构造方法,初始化对应的处理器
    Subject(SubjectHandler handler) {
        this.handler = handler;
    }

    // 对外暴露的统一处理入口
    public void processData(JSONObject data) {
        handler.handle(data);
    }

    // 原来的业务方法可以封装在这里作为静态方法,或者直接调用外部类的方法
    private static void sendFoo1(String param1, String param2) {
        // SEND_VERIFY对应的原有业务逻辑
    }

    private static void foo2(int param1, int param2) {
        // DO_FOO2对应的原有业务逻辑
    }

    private static void doFoo3For(String param) {
        // DO_FOO3对应的原有业务逻辑
    }
}

步骤3:简化控制器代码

原来的switch分支可以完全删掉,只需要一行代码就能完成所有类型的处理:

Subject subject = ...; // 从请求中获取枚举值
JSONObject data = request.getData("data");
// 不用关心具体是哪个Subject,直接调用统一方法
subject.processData(data);

复杂场景扩展:独立处理器类

如果某个Subject的处理逻辑很复杂,或者需要依赖其他服务(比如Spring中的Bean),可以把处理器做成独立的类,再注入到枚举中:

// 独立的处理器类,处理SEND_VERIFY逻辑
public class SendVerifyHandler implements SubjectHandler {
    private final VerifyService verifyService;

    // 构造注入依赖(Spring环境下可通过@Autowired实现)
    public SendVerifyHandler(VerifyService verifyService) {
        this.verifyService = verifyService;
    }

    @Override
    public void handle(JSONObject data) {
        verifyService.sendVerificationCode(data.getString("foo1_1"), data.getString("foo1_2"));
    }
}

然后修改枚举,注入这个处理器:

public enum Subject {
    SEND_VERIFY(new SendVerifyHandler(verifyService)),
    // 其他枚举常量...

    private final SubjectHandler handler;

    Subject(SubjectHandler handler) {
        this.handler = handler;
    }

    public void processData(JSONObject data) {
        handler.handle(data);
    }
}

为什么这个方案更优?

  • 严格符合开闭原则:新增Subject类型时,只需要在枚举里添加一个新常量并绑定逻辑,完全不用修改原有控制器或其他枚举代码。
  • 逻辑高度内聚:每个Subject的处理逻辑和枚举值绑定在一起,不用在switch里找分散的代码,可读性和维护性大幅提升。
  • 扩展性极强:不管是简单的Lambda逻辑,还是需要依赖注入的复杂业务,都能轻松适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:39:54