1、简介
枚举的基础使用不需要多说,本篇讲述的是进阶使用。
对于枚举的定义,类似接口但是有自己的构造方法,枚举不可以使用extends继承关键字,但是可以实现接口,特点描述如下
2、枚举与字典
字典:通常用于维护可变少,无流程的常量,存储在数据库中
枚举:不可变常量,每一种状态可能都会影响到流程,存储在java代码中
3、枚举-接口与lombok的结合使用
lombok的@Getter注解简化了属性的get()方法,interface定义get方法的规则
因此需要统一枚举的属性,定义枚举需要实现的公共接口
定义接口 FlowBaseEnum.class
1 2 3 4 5 6 7
| public interface FlowBaseEnum {
String getKey();
String getValue();
}
|
枚举
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
@Getter @AllArgsConstructor public enum DeviceBindStatus implements FlowBaseEnum {
LOCKED("1","锁定"),
UNLOCKED("2","未锁定"), ;
private final String key;
private final String value;
}
|
上述枚举 属性 key
value
为固定字段,接口方法为属性的get方法
4、接口的作用
单个枚举的使用看不出接口的效果,对于接口的定义,通过接口来统一的管理流程类枚举
应用场景:设备绑定状态下拉框数据
定义流程枚举工具类:FlowEnumUtils
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class FlowEnumUtils {
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、枚举的分组
场景:不同订单类型下,订单中的数据类型不相同。
如订单类型分为
每个类型中所对应的数据是不相同的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
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、枚举中的一对多分组
这里结合的是上面两种方式的一个进阶,相当于对枚举分组的一个实现,使用场景:
每个订单类型下,对应多个不同的数据类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
@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;
public abstract <T extends IOrderDataTypes> List<T> getOrderTypes(); }
|
这里OrderDataType
枚举中定义了3中订单类型,而如果需要实现每种类型对应多个数据类型,则需要定义一个抽象方法,返回的是数据类型列表,方法的返回值数据类型则是IOrderDataTypes
的实现类。在上面枚举的分组
中已经定义了一个IOrderDataTypes
。
1 2 3 4
|
List<IOrderDataTypes> orderTypes = OrderDataType.ORTHODONTICS.getOrderTypes(); orderTypes.forEach(System.out::println);
|
可以把枚举定义成接口,枚举中定义的值为接口的实现类,枚举中只能定义抽象方法,不能定义普通方法,而实现类中必须实现抽象方法
总结
了解枚举与字典的使用场景,可以是开发变的更高效,以前使用字典维护项目中的流程状态,开发起来很繁琐,因此关于流程的状态个人觉得不太适合使用字典维护。
灵感来自书籍《On Java 8 进阶版》