在java中实现两层关联的枚举

在实际开发中,有各种奇葩的需求,我就遇到一次,在调度任务建依赖的时候,需要选择依赖的周期和周期的值

比如下面这样,如果你依赖天任务,那么还需要选择今天、昨天还是前七天?

周期周期值描述
day today,last7Days,last3Days,last2Days,last1Days 今天、昨天、前两天、前三天、前七天
month thisMonth,lastMonth,lastMonthBegin,lastMonthEnd 本月、上月、上月初、上月末
week thisWeek,lastWeek,lastWednesday 本周、上周、上周一~上周日
hour last3Hours,last24Hours,currentHour,last1Hour 当前小时、前1小时,前2小时,前3小时,前24小时

显而易见,这有两层枚举,关键是怎么实现呢?

枚举类已经有了默认父类,继承是没法考虑了,只能考虑组合

首先定义父类

复制代码
//日期周期,父枚举
public enum Period {
    DAY("日"),
    MONTH("月"),
    WEEK("周"),
    HOUR("时");

    private String desc;

    Period(String desc) {
        this.desc = desc;
    }

 
复制代码

然后定义子类

复制代码
public enum PeriodValue {
    today("今天", Period.DAY),
    last7Days("前7天", Period.DAY),

    thisMonth("本月", Period.MONTH),
    lastMonth("上月", Period.MONTH),

    thisWeek("本周", Period.WEEK),
    lastWeek("上周", Period.WEEK),

    currentHour("当前小时", Period.HOUR),
    last1Hour("前1小时", Period.HOUR);

    private String desc;
    private Period parent;

    PeriodValue(String desc, Period parent) {
        this.desc = desc;
        this.parent = parent;
    }

    public String getDesc() {
        return desc;
    }

    public Period getParent() {
        return parent;
    }

    /**
     * 方法一:在子枚举定义静态方法,根据父枚举,得到子枚举列表
     *
     * @param parent
     * @return
     */
    public static List<PeriodValue> getPeriodValues(Period parent) {
        return Arrays.stream(PeriodValue.values()).filter(periodValue -> {
            return periodValue.getParent().equals(parent);
        }).collect(Collectors.toList());

    }


    public static void main(String[] args) {
        Period day = Period.DAY;
        //方法一
        List<PeriodValue> periodValues = PeriodValue.getPeriodValues(day);
        System.out.println(day);
        System.out.println(periodValues);
      
    }
}
复制代码

我们在每个子枚举的属性中标记了子枚举对应的父枚举,进而定义了一个静态方法根据父枚举获取子枚举列表

执行下:

DAY
[today, last7Days]

的确建立了父子枚举的关系

但还有另外一种实现方法,就是通过父枚举直接获取子枚举列表

下面是修改后的父枚举实现:

复制代码
public enum Period {
    DAY("日"){
        @Override
        List<PeriodValue> getChildren() {
            return Arrays.stream(PeriodValue.values()).filter(periodValue -> {
                return periodValue.getParent().equals(this);
            }).collect(Collectors.toList());
        }
    },
    MONTH("月"){
        @Override
        List<PeriodValue> getChildren() {
            return Arrays.stream(PeriodValue.values()).filter(periodValue -> {
                return periodValue.getParent().equals(this);
            }).collect(Collectors.toList());
        }
    },
    WEEK("周"){
        @Override
        List<PeriodValue> getChildren() {
            return Arrays.stream(PeriodValue.values()).filter(periodValue -> {
                return periodValue.getParent().equals(this);
            }).collect(Collectors.toList());
        }
    },
    HOUR("时"){
        @Override
        List<PeriodValue> getChildren() {
            return Arrays.stream(PeriodValue.values()).filter(periodValue -> {
                return periodValue.getParent().equals(this);
            }).collect(Collectors.toList());
        }
    };

    private String desc;

    Period(String desc) {
        this.desc = desc;
    }

    /**
     * 方法二:在父枚举定义抽象类,直接从父枚举获取子枚举列表
     * @return
     */
    abstract List<PeriodValue> getChildren();
复制代码

此时就可以通过父枚举直接得到子枚举列表,示例如下

复制代码
public static void main(String[] args) {
        Period day = Period.DAY;
        //方法一
        List<PeriodValue> periodValues = PeriodValue.getPeriodValues(day);
        System.out.println(day);
        System.out.println(periodValues);
        //方法二
        List<PeriodValue> children = day.getChildren();
        System.out.println(children);
    }
复制代码

结果是一样的,虽然代码有些冗余,但在使用的时候的确是简单了很多,逻辑也更清晰了。

备注:

方法一其实还有另外一个用途,假如子枚举不仅要根据父枚举进行筛选,还有其他筛选条件,类似于有多个父类

此时还可以在子枚举中可以再标记一个属性,再定义一个静态方法进行多条件筛选,非常灵活,而方法二是实现不了这种多条件筛选的。

posted @   Mars.wang  阅读(1095)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2019-01-28 如何理解<T extends Comparable<? super T>>
点击右上角即可分享
微信分享提示