专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

枚举类的业务实践

业务场景

在进行业务开发时经常会有状态值的业务需要,例如一场考试有未开考、考试中、考试结束等状态或者一年四季有春天、夏天、秋天、冬天等状态。从前台传参到我们的业务模型再到数据库,其实这些状态是贯穿整个开发流程的。如果仅仅使用1、2、3、4来代表春夏秋冬的话,那代码的自解释能力就太差了。那如何利用好枚举类来更优雅的编码呢?

枚举类需要满足的功能

1、 消除代码中的魔术数
2、 根据数值获取状态的名称
3、 根据数值获取状态
4、 获取数值和状态名称为键值对的Map作为前端筛选项。

第一种枚举类实现

public enum SeasonEnum {

    /**/
    SPRING(1,"春天"),
    SUMMER(2,"夏天"),
    AUTUMN(3,"秋天"),
    WINTER(4,"冬天");

    public final int id;
    public final String desc;

    SeasonEnum(int id, String desc) {
        this.id = id;
        this.desc = desc;
    }

    /**
     * 根据数值获取对应的枚举
     * @param id
     * @return
     */
    public static SeasonEnum getEnumById(int id) {
        for (SeasonEnum seasonEnum : SeasonEnum.values()) {
            if (seasonEnum.id == id) {
                return seasonEnum;
            }
        }
        return null;
    }

    /**
     * 根据数值获取对应的枚举描述
     * @param id
     * @return
     */
    public static String getEnumDescById(int id) {
        final String unknown = "未知";
        for (SeasonEnum seasonEnum : SeasonEnum.values()) {
            if (seasonEnum.id == id) {
                return seasonEnum.desc;
            }
        }
        return unknown;
    }

    /**
     * 获取数值-描述键值对map
     * @return
     */
    public static Map getEnumMap() {
        Map<Object, Object> map = new HashMap<>();
        for (SeasonEnum seasonEnum : SeasonEnum.values()) {
            map.put(seasonEnum.id, seasonEnum.desc);
        }
        return map;
    }

}

测试实现:

    int seasonType = 2;
    // 如果是夏天的话
    if (seasonType == SeasonEnum.SUMMER.id) {
        System.out.println("穿短袖!");
    }
    // 根据id获取对应枚举类
    System.out.println(SeasonEnum.getEnumById(seasonType));
    // 根据id获取对应枚举类描述
    System.out.println(SeasonEnum.getEnumDescById(seasonType));
    // 获取id-描述键值对map
    Map seasonMap = SeasonEnum.getEnumMap();
    System.out.println(seasonMap);

运行结果:

穿短袖!
SPRING
春天
{1=春天, 2=夏天, 3=秋天, 4=冬天}

通过通过枚举类,以及getEnumById()、getEnumDescById()、getEnumMap()方法我们实现了一开始设置业务关于枚举类的需求。

但是当系统内的枚举类剧增的时候,所有枚举类都需要实现getEnumById()、getEnumDescById()、getEnumMap()这三个方法。能不能将这三个方法都抽取出来呢?

第二种枚举类实现

因为enum枚举类其实也是一个Java类,一个相当于继承Enum的类,所以不能再通过继承来声明共有的方法,而只能使用接口来声明共有的方法。

我们通过一个IEnum接口来声明共有的getId()、getDesc()方法。

public interface IEnum<V, D> {
    /**
     * 获取id
     * @return
     */
    V getId();
    /**
     * 获取描述
     * @return
     */
    D getDesc();
}

实现了IEnum接口的SeasonEnum枚举类。

public enum SeasonEnum implements IEnum {

    /**/
    SPRING(1,"春天"),
    SUMMER(2,"夏天"),
    AUTUMN(3,"秋天"),
    WINTER(4,"冬天");

    public final int id;
    public final String desc;

    SeasonEnum(int id, String desc) {
        this.id = id;
        this.desc = desc;
    }

    @Override
    public Object getId() {
        return id;
    }

    @Override
    public Object getDesc() {
        return desc;
    }
}

接着我们再根据一个枚举工具类EnumUtil来封装getEnumById()、getEnumDescById()、getEnumMap()这三个方法。

public class EnumUtil {

    private static final String UNKNOW = "未知";

    /**
     * 根据id获取枚举类
     * @param id
     * @param type
     * @param <E>
     * @param <V>
     * @return
     */
    public static<E extends IEnum, V> E getEnumById(V id, Class<E> type) {
        if (!type.isEnum()) {
            throw new IllegalArgumentException("Type: " + type + " must be a enum");
        }

        for (E iEnum : type.getEnumConstants()) {
            if (iEnum.getId().equals(id)) {
                return iEnum;
            }
        }
        return null;
    }

    /**
     * 根据id获取对应枚举的描述
     * @param id
     * @param type
     * @param <E>
     * @param <V>
     * @return
     */
    public static <E, V> E getEnumDescById(V id, Class<? extends IEnum> type) {

        IEnum iEnum = getEnumById(id, type);

        if (iEnum != null) {
            return (E) iEnum.getDesc();
        } else {
            return (E) UNKNOW;
        }

    }

    /**
     * 获取枚举的id-描述键值对
     * @param type
     * @return
     */
    public static Map<Object, Object> getEnumMap(Class<? extends IEnum> type) {

        if (!type.isEnum()) {
            throw new IllegalArgumentException("Type: " + type + " must be a enum");
        }

        Map<Object, Object> map = new HashMap<>(type.getEnumConstants().length);

        for (IEnum iEnum : type.getEnumConstants()) {
            map.put(iEnum.getId(), iEnum.getDesc());
        }

        return map;
    }

}

测试实现:

  public static void main(String[] args) {

        int seasonType = 2;
        // 如果是夏天的话
        if (seasonType == SeasonEnum.SUMMER.id) {
            System.out.println("穿短袖!");
        }
        // 根据id获取对应枚举类
        System.out.println(EnumUtil.getEnumById(seasonType, SeasonEnum.class));
        // 根据id获取对应枚举类描述
        System.out.println(EnumUtil.getEnumDescById(seasonType, SeasonEnum.class));
        // 获取id-描述键值对map
        Map seasonMap = EnumUtil.getEnumMap(SeasonEnum.class);
        System.out.println(seasonMap);

        switch (EnumUtil.getEnumById(seasonType, SeasonEnum.class)) {

            case SUMMER:
                System.out.println("穿短袖!");
                break;
            case WINTER:
                System.out.println("穿羽绒服!");
                break;
            case SPRING:
            case AUTUMN:
                System.out.println("穿春秋装!");

            default:
                break;

        }

    }

运行结果:

穿短袖!
SUMMER
夏天
{1=春天, 2=夏天, 3=秋天, 4=冬天}
穿短袖!

通过IEnum接口以及EnumUtil的封装我们消除了之前Enum类当中冗余的代码,并较为良好的利用了枚举类的优点。

有其他好的枚举业务实现,恳请网友不吝赐教指点一下~

笔者个人心得,如有错误望网友评论指正。

https://tech.souyunku.com

文章永久链接:https://tech.souyunku.com/27384

未经允许不得转载:搜云库技术团队 » 枚举类的业务实践

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们