如何在程序中避免出现大量if和case

在 Java 开发中,想要避免出现大量 if...elseswitch...case,可以使用多种设计模式和技巧来"消除条件分支"。下面总结几种常用、实战有效的方案👇


🧭 一、使用 策略模式(Strategy Pattern)

👉 最经典、最推荐的方式。

✅ 使用场景

当你有一堆"根据类型执行不同逻辑"的判断,比如:

csharp 复制代码
if (type.equals("EMAIL")) { ... }
else if (type.equals("SMS")) { ... }
else if (type.equals("PUSH")) { ... }

✅ 优雅改造

定义一个通用接口 NotificationStrategy

arduino 复制代码
public interface NotificationStrategy {
    void send(String message);
}

不同策略实现类:

typescript 复制代码
@Component("EMAIL")
public class EmailNotificationStrategy implements NotificationStrategy {
    public void send(String message) {
        System.out.println("发送邮件: " + message);
    }
}

@Component("SMS")
public class SmsNotificationStrategy implements NotificationStrategy {
    public void send(String message) {
        System.out.println("发送短信: " + message);
    }
}

工厂自动管理策略:

typescript 复制代码
@Service
public class NotificationService {
    private final Map<String, NotificationStrategy> strategyMap;

    @Autowired
    public NotificationService(Map<String, NotificationStrategy> strategyMap) {
        this.strategyMap = strategyMap;
    }

    public void notify(String type, String message) {
        NotificationStrategy strategy = strategyMap.get(type);
        if (strategy != null) {
            strategy.send(message);
        } else {
            throw new IllegalArgumentException("未知通知类型: " + type);
        }
    }
}

调用:

arduino 复制代码
notificationService.notify("EMAIL", "你好");

好处:

  • 新增类型只需新增类,不动原逻辑
  • Spring 自动注入 Map<String, BeanName>
  • 无需写 if / case

🧩 二、使用 枚举 + Lambda + Map

适合一些轻量级逻辑分派,不用创建一堆类。

css 复制代码
public enum Operation {
    ADD((a, b) -> a + b),
    SUB((a, b) -> a - b),
    MUL((a, b) -> a * b),
    DIV((a, b) -> a / b);

    private final BiFunction<Integer, Integer, Integer> function;

    Operation(BiFunction<Integer, Integer, Integer> function) {
        this.function = function;
    }

    public int apply(int a, int b) {
        return function.apply(a, b);
    }
}

调用:

arduino 复制代码
int result = Operation.MUL.apply(2, 3); // 输出 6

🧮 三、使用 Map 映射表(函数表)

适合简单分派逻辑。

rust 复制代码
Map<String, Runnable> actions = new HashMap<>();
actions.put("A", () -> System.out.println("执行逻辑 A"));
actions.put("B", () -> System.out.println("执行逻辑 B"));

String type = "A";
actions.getOrDefault(type, () -> System.out.println("默认逻辑")).run();

✅ 比 if/else 更直观,支持动态注册。


🧱 四、使用 责任链模式(Chain of Responsibility)

适合"逐步判断、条件过滤"的业务,比如审批、数据校验。

csharp 复制代码
public abstract class Handler {
    protected Handler next;
    public void setNext(Handler next) { this.next = next; }
    public abstract void handle(Request request);
}

public class AuthHandler extends Handler {
    public void handle(Request req) {
        if (req.isAuthenticated()) {
            if (next != null) next.handle(req);
        } else {
            System.out.println("未登录");
        }
    }
}

链式执行:

ini 复制代码
authHandler.setNext(validationHandler);
validationHandler.setNext(businessHandler);
authHandler.handle(request);

✅ 可自由扩展处理链,避免多层 if 嵌套。


🧰 五、使用 状态模式(State Pattern)

适合"根据状态执行不同逻辑"的情况,比如流程节点、订单状态、任务状态。

csharp 复制代码
public interface State {
    void handle();
}

public class PendingState implements State {
    public void handle() { System.out.println("等待审批"); }
}

public class ApprovedState implements State {
    public void handle() { System.out.println("已通过"); }
}

上下文:

typescript 复制代码
public class Context {
    private State state;
    public void setState(State state) { this.state = state; }
    public void handle() { state.handle(); }
}

✅ 对应状态 -> 行为的分离,新增状态不用改老代码。


🧠 六、反射 + 注解(高级玩法)

可以用自定义注解 + 扫描注册的方式,动态调用方法,而不用写 case:

less 复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ActionType {
    String value();
}

定义方法:

less 复制代码
@ActionType("A")
public void doA() { ... }

@ActionType("B")
public void doB() { ... }

初始化时扫描并放入 Map<String, Method>,根据类型动态调用。


✅ 总结对比

场景 推荐方式 说明
多种类型执行不同逻辑 策略模式 Spring 最佳实践
简单分派逻辑 Map 或枚举 Lambda 少量逻辑、轻量级
逐步过滤、审批流程 责任链模式 解耦多层判断
不同状态不同行为 状态模式 适合流程引擎
动态注册调用 注解 + 反射 框架级玩法
相关推荐
武子康几秒前
大数据-156 Apache Druid+Kafka 实时分析实战:JSON 拉平摄取与 SQL 指标全流程
大数据·后端·nosql
华仔啊9 分钟前
MySql 的 VARCHAR 和 TEXT 怎么选?大厂都在用的文本存储方案
后端·mysql
脉动数据行情12 分钟前
Go语言对接股票、黄金、外汇API实时数据教程
开发语言·后端·golang
kfyty72513 分钟前
loveqq 作为网关框架时如何修改请求体 / 响应体,和 spring 又有什么区别?
后端·架构
root_zhb30 分钟前
List.contains踩坑
java·list
曾经的三心草34 分钟前
Java数据结构-List-栈-队列-二叉树-堆
java·数据结构·list
aiopencode37 分钟前
Swift 加密工具推荐,构建可落地的多层安全体系(源码混淆+IPA 加固+动态对抗+映射治理)
后端
Moe4881 小时前
合并Pdf、excel、图片、word为单个Pdf文件的工具类(技术点的选择与深度解析)
java·后端
又过一个秋1 小时前
CyberRT Transport传输层设计
后端
Java水解1 小时前
20个高级Java开发面试题及答案!
spring boot·后端·面试