枚举进阶用法Enum——小Tips

1、简介

枚举的基础使用不需要多说,本篇讲述的是进阶使用。

对于枚举的定义,类似接口但是有自己的构造方法,枚举不可以使用extends继承关键字,但是可以实现接口,特点描述如下

  • 枚举不可以继承
  • 可以实现接口
  • 可以有抽象方法

2、枚举与字典

字典:通常用于维护可变少,无流程的常量,存储在数据库中

  • 一般用于存储如性别、是否、开关等

枚举:不可变常量,每一种状态可能都会影响到流程,存储在java代码中

  • 如订单的状态,使用的是枚举存储

3、枚举-接口与lombok的结合使用

lombok的@Getter注解简化了属性的get()方法,interface定义get方法的规则
因此需要统一枚举的属性,定义枚举需要实现的公共接口

定义接口 FlowBaseEnum.class

public interface FlowBaseEnum {

    String getKey();

    String getValue();

}

设备绑定状态枚举类

/**
 * 设备绑定状态枚举
 * @author wuhao	
 * @date 2022/11/1 15:25
 */
@Getter
@AllArgsConstructor
public enum DeviceBindStatus implements FlowBaseEnum {

    LOCKED("1","锁定"),

    UNLOCKED("2","未锁定"),
    ;

    private final String key;

    private final String value;

}

上述枚举 属性 key value为固定字段,接口方法为属性的get方法

4、接口的作用

单个枚举的使用看不出接口的效果,对于接口的定义,通过接口来统一的管理流程类枚举

应用场景:设备绑定状态下拉框数据

定义流程枚举工具类:FlowEnumUtils


/**
 * @author wuhao
 * @date 2022/11/4 16:34
 */
public class FlowEnumUtils {
 /**
     * 获取枚举下拉
     *
     * @param cls 枚举class类
     * @param <T>
     * @return
     */
    public static <T extends FlowBaseEnum> List<OptionLabel<String, String>> getOptionList(Class<T> cls) {
        Assert.notNull(cls);
        T[] constants = cls.getEnumConstants();
        return Arrays.stream(constants).map(t -> {
            OptionLabel<String, String> optionLabel = new OptionLabel<>();
            optionLabel.setLabel(t.getValue());
            optionLabel.setValue(t.getKey());
            return optionLabel;
        }).collect(Collectors.toList());
    }
}

OptionLabel为通用的下拉实体,只有label与value两个属性

这个方法可以看出来为什么要定义接口了吧

使用泛型,T的类型为FlowBaseEnum接口的实现类,当然实现类必须为枚举,不然cls.getEnumConstants()会报错,通过getEnumConstants()方法获取枚举数组,返回的就是枚举中所有的构造方法,通过接口定义的getKey()与getValue()获取key value封装成下拉实体。

因此定义接口是为了统一维护枚举,并加以扩展定制化

5、枚举的分组

场景:不同订单类型下,订单中的数据类型不相同。
如订单类型分为

  • 修复类型订单
  • 种植类型订单
  • 正畸类型订单

每个类型中所对应的数据是不相同的

/** 
 * 订单数据类型接口
 * @author wuhao
 * @date 2022/11/1 18:12
 */
public interface IOrderDataTypes {

    /**
     * 修复类型
     */
    @Getter
    @AllArgsConstructor
    enum REPAIR implements IOrderDataTypes {
        DATA_INTACT("数据完整性"),
        MARGIN("边缘"),
        RECESSED_AND_POSITION_PATH("倒凹&就位道"),
        ;

        private final String description;
    }

    /**
     * 种植类型
     */
    @Getter
    @AllArgsConstructor
    enum PLANT implements IOrderDataTypes {
        DATA_INTACT("数据完整性"),
        PLANTING_SCANNING_ROD("种植扫描杆"),
        ;
        private final String description;
    }

    /**
     * 正畸类型
     */
    @Getter
    @AllArgsConstructor
    enum ORTHODONTICS implements IOrderDataTypes {
        DATA_INTACT("数据完整性"),
        BITE_THE_JAW("咬颌"),
        ;

        private final String description;
    }

}

接口中可定义多个枚举类,这里接口的作用仅仅是做一个分组的作用

6、枚举中的一对多分组

这里结合的是上面两种方式的一个进阶,相当于对枚举分组的一个实现,使用场景:
每个订单类型下,对应多个不同的数据类型

/**
 * 订单数据类型
 * @author wyj
 * @date 2022/11/1 17:46
 */
@Getter
@AllArgsConstructor
public enum OrderDataType implements FlowBaseEnum {

    REPAIR("1","牙齿修复"){
        @Override
        public List<IOrderDataTypes.REPAIR> getOrderTypes() {
            return Arrays.stream(IOrderDataTypes.REPAIR.values()).collect(Collectors.toList());
        }
    },

    PLANT("2","牙齿种植"){
        @Override
        public List<IOrderDataTypes.PLANT> getOrderTypes() {
            return Arrays.stream(IOrderDataTypes.PLANT.values()).collect(Collectors.toList());
        }
    },

    ORTHODONTICS("3","牙齿正畸"){
        @Override
        public List<IOrderDataTypes.ORTHODONTICS> getOrderTypes() {
            return Arrays.stream(IOrderDataTypes.ORTHODONTICS.values()).collect(Collectors.toList());
        }
    },

    ;

    private final String key;

    private final String value;

    /**
     * 获取类型中的详细类型
     * @return
     */
    public abstract <T extends IOrderDataTypes> List<T> getOrderTypes();
}

这里OrderDataType枚举中定义了3中订单类型,而如果需要实现每种类型对应多个数据类型,则需要定义一个抽象方法,返回的是数据类型列表,方法的返回值数据类型则是IOrderDataTypes的实现类。在上面枚举的分组中已经定义了一个IOrderDataTypes

// 要获取某一个类型中的数据类型列表
// 获取牙齿正畸订单数据类型列表标识
List<IOrderDataTypes> orderTypes = OrderDataType.ORTHODONTICS.getOrderTypes();
orderTypes.forEach(System.out::println);

在这里插入图片描述

可以把枚举定义成接口,枚举中定义的值为接口的实现类,枚举中只能定义抽象方法,不能定义普通方法,而实现类中必须实现抽象方法

总结

了解枚举与字典的使用场景,可以是开发变的更高效,以前使用字典维护项目中的流程状态,开发起来很繁琐,因此关于流程的状态个人觉得不太适合使用字典维护。

灵感来自书籍《On Java 8 进阶版》

ps

没事可以来我的破站逛逛~~欢迎大家

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值