【问题标题】:Should an enum have 2 separate value sets if they are related?如果它们是相关的,枚举是否应该有 2 个单独的值集?
【发布时间】:2021-05-31 15:02:24
【问题描述】:

这个问题是关于Java Enums的重用

假设我有一个枚举

public enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY SATURDAY, SUNDAY
}

现在,在一个业务用例中,我还需要将今天、明天和昨天视为日子。虽然它们是相关的概念,但将它们放在同一个枚举中感觉不对。

我们是否应该创建一个新的枚举,或者是否有任何理由重载相同的 Days 枚举并在其中添加这 3 个值。

public enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY SATURDAY, SUNDAY, TODAY, TOMORROW, YESTERDAY
}

更新1: 上面的枚举只是为了提出用例而已。 我在代码库中的枚举是特定于业务的,但想法是新枚举值在上面的示例中以类似的模糊类型相关,但它们肯定属于不同的值集。

【问题讨论】:

  • 不要重新发明轮子(再次)。使用java.time 中的类。见DayOfWeek.plus(long)
  • 我建议使用不同的枚举,因为 2 具有不同的含义。尽管它们都指的是天,但它们与不同的事物相关:工作日与一周相关,而昨天等与当天相关。也可以这样想:一组数据的枚举值,因此一条数据只能有一个值(例如工作日)。如果您将工作日和 TODAY 之类的偏移量混合在一起,那么“今天”可能有 2 个含义:今天和星期一。
  • 从该提议的枚举看来,TOMORROW 似乎不是星期一、星期二、星期三、星期四、星期五、星期六或星期日之一。换句话说,不,我可能不会那样做。
  • @Elliot :上面的枚举只是为了提出用例而已。我在代码库中的枚举是特定于业务的,而不是工作日:),但想法是新的枚举值在上面的示例中以类似的模糊类型相关

标签: java oop design-patterns enums


【解决方案1】:

您可以实现函数而不是扩展给定的enum,例如

enum Days {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(yesterday(Days.SUNDAY)); // SATURDAY
        System.out.println(yesterday(Days.MONDAY)); // SUNDAY
        System.out.println(yesterday(Days.TUESDAY)); // MONDAY

        System.out.println(tomorrow(Days.SUNDAY)); // MONDAY
        System.out.println(tomorrow(Days.MONDAY)); // TUESDAY
        System.out.println(tomorrow(Days.TUESDAY)); // WEDNESDAY
    }

    static Days yesterday(Days day) {
        Days[] days = Days.values();
        int ordinal = day.ordinal();
        int index = ordinal == 0 ? days.length - 1 : ordinal - 1;
        return days[index];
    }

    static Days tomorrow(Days day) {
        Days[] days = Days.values();
        int ordinal = day.ordinal();
        int index = ordinal == days.length - 1 ? 0 : ordinal + 1;
        return days[index];
    }

    static Days today(Days day) {
        return day;
    }
}

【讨论】:

    【解决方案2】:

    昨天、今天和明天是一周中当前日期的相对位置,不是值。这就是方法有用的原因:声明某事物与其他事物相关。因此,使用 DayOfWeek:

    DayOfWeek yesterday(DayOfWeek day){ return day.plus(-1);}
    
    DayOfWeek today(DayOfWeek day){ return day;}
    
    DayOfWeek tomorrow(DayOfWeek day){ return day.plus(1);}
    

    实现起来更简单。但是使用你的枚举:

    Days yesterday(Days day){ 
      return day.ordinal() == 0 ? 
        Days.values()[Days.SUNDAY.ordinal()]: 
        Days.values()[day.ordinal()-1];
    }
    
    Days today(Days day){ return day; }
    
    Days tomorrow(Days day){
      return day.ordinal() == 6 ? 
        Days.values()[Days.MONDAY.ordinal()]: 
        Days.values()[day.ordinal()-1];
    }
    

    【讨论】:

    • 为什么是day.plus(-1) 而不是day.minus(1)
    • 我的用例是一个具有业务特定值的枚举。我只是想借助 Week days 示例来展示新价值观和旧价值观之间的模糊关系。对于需要添加的新值,我有类似的模糊关系。因此正在考虑创建一个新的枚举或重用现有的枚举
    • 您能解释一下您的业务案例中关系的性质吗?
    【解决方案3】:

    可能有办法,但如果有,那绝对不理想。 cmets也完美地描述了这个问题。枚举是一组用于单一目的的定义值。虽然“星期几”和“相对日期”可能产生相同的结果,但并不理想。

    因此,为了简洁起见,我建议您为每个枚举值使用不同的枚举值,如果您特别需要枚举而不是像 @Victor (https://stackoverflow.com/a/67776586/6035548) 在他的回答中那样写它

    【讨论】:

      猜你喜欢
      • 2014-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 2012-11-03
      • 2014-04-09
      • 2022-01-13
      • 1970-01-01
      相关资源
      最近更新 更多