Java枚举调用流程如何规整

wen java案例 31

本文目录导读:

Java枚举调用流程如何规整

  1. 模式一:基于属性的数据驱动(最常见)
  2. 模式二:抽象方法 + 策略模式(行为驱动)
  3. 模式三:函数式接口 + 枚举(Lambda版本)
  4. 规整流程的黄金原则
  5. 完整调用示例(业务场景)
  6. 什么时候不适合用枚举?

针对Java枚举的调用流程规整,核心在于告别散乱的switch/case和if-else,利用枚举自身特性实现逻辑内聚,以下是三种主流且规范的调用模式:

基于属性的数据驱动(最常见)

枚举不仅仅是常量,可以携带数据,调用时直接获取属性值。

public enum OrderStatus {
    PENDING(0, "待支付"),
    PAID(1, "已支付"),
    SHIPPED(2, "已发货"),
    COMPLETED(3, "已完成");
    private final int code;
    private final String desc;
    // 构造器、getter...
    OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    public int getCode() { return code; }
    public String getDesc() { return desc; }
    // 工厂方法:根据code获取枚举实例
    public static OrderStatus fromCode(int code) {
        for (OrderStatus status : values()) {
            if (status.code == code) return status;
        }
        throw new IllegalArgumentException("Invalid code: " + code);
    }
}
// 调用端
OrderStatus status = OrderStatus.fromCode(1);
System.out.println(status.getDesc()); // 输出"已支付"

抽象方法 + 策略模式(行为驱动)

每个枚举实例实现不同的业务逻辑,调用时直接执行,无需条件判断。

public enum NotificationChannel {
    EMAIL {
        @Override
        public void send(String message) {
            // 调用邮件API
            System.out.println("发送邮件: " + message);
        }
    },
    SMS {
        @Override
        public void send(String message) {
            // 调用短信API
            System.out.println("发送短信: " + message);
        }
    },
    WECHAT {
        @Override
        public void send(String message) {
            // 调用微信API
            System.out.println("发送微信: " + message);
        }
    };
    // 抽象方法,每个枚举实例必须实现
    public abstract void send(String message);
}
// 调用端(极简)
NotificationChannel channel = NotificationChannel.EMAIL;
channel.send("您的订单已发货"); // 自动匹配对应的发送逻辑

函数式接口 + 枚举(Lambda版本)

对于Java 8+,使用FunctionConsumer进一步简化。

import java.util.function.Consumer;
public enum Calculator {
    ADD((a, b) -> a + b),
    SUBTRACT((a, b) -> a - b),
    MULTIPLY((a, b) -> a * b),
    DIVIDE((a, b) -> {
        if (b == 0) throw new ArithmeticException("/ by zero");
        return a / b;
    });
    private final IntBinaryOperator operator;
    Calculator(IntBinaryOperator operator) {
        this.operator = operator;
    }
    public int apply(int a, int b) {
        return operator.applyAsInt(a, b);
    }
}
// 调用端
int result = Calculator.ADD.apply(10, 5); // 15

规整流程的黄金原则

原则 说明 反例
内聚性 业务逻辑封装在枚举内部,调用端只负责选择实例 在service层写switch(status){...}
单一职责 枚举只做一件事:要么存数据,要么定义行为,要么做映射 既写SQL又写渲染逻辑
工厂方法 提供fromCodeof等静态方法实现反查 暴露code/dbValue字段让外部判断
接口分离 如果逻辑复杂(>3行),抽取为独立策略类 在枚举抽象方法里写100行代码

完整调用示例(业务场景)

// 1. 定义枚举
public enum ReimburseType {
    TRAVEL(1, "差旅费") {
        @Override
        public boolean needInvoice() { return true; }
    },
    OFFICE(2, "办公用品") {
        @Override
        public boolean needInvoice() { return true; }
    },
    SUBSIDY(3, "补贴") {
        @Override
        public boolean needInvoice() { return false; }
    };
    private final int code;
    private final String name;
    ReimburseType(int code, String name) {
        this.code = code;
        this.name = name;
    }
    // 行为抽象
    public abstract boolean needInvoice();
    // 工厂方法
    public static ReimburseType fromCode(int code) {
        return Arrays.stream(values())
            .filter(t -> t.code == code)
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unknown code: " + code));
    }
    // getters...
}
// 2. 调用端(业务层)
public class ReimburseService {
    public void submitReimburse(int typeCode, double amount) {
        ReimburseType type = ReimburseType.fromCode(typeCode);
        // 不需要if-else,直接调用枚举行为
        if (type.needInvoice()) {
            // 检查发票
        }
        // 存入数据库时用code
        saveToDB(type.getCode(), amount);
        // 返回给前端用name
        log.info("报销类型: {}", type.getName());
    }
}

什么时候不适合用枚举?

  • 枚举项超过20个:考虑用数据表 + 缓存
  • 需要动态扩展:枚举是编译期固定的,若需运行时添加,改用数据库配置
  • 跨服务共享:枚举定义在公共模块,修改需重新部署所有依赖方

规整的核心思想:让枚举成为“能思考的数据”,而不是“被判断的常量”

抱歉,评论功能暂时关闭!