如何在java中提供枚举值的实现?

falq053o  于 2021-07-09  发布在  Java
关注(0)|答案(8)|浏览(395)

我有一个枚举类,它的值应该随时间增长,我希望添加新枚举值的用户也在某处提供实现。但我不知道如何迫使他们提供弹劾,因为弹劾将在其他类。例如。

public enum DayType {
    SUNDAY,
    MONDAY;
}

在课堂上介绍

class X{
DateType dateType;
..
}

在别的班级里用过

if (x.getDateType().equals(DayType.SUNDAY)) {
...
}else if(x.getDateType().equals(DayType.MONDAY)){
..
}

因此,如果有人添加了datetype,那么他应该被迫在上面的if-else逻辑中添加impement。如果可能的话,最好增加功能接口?
我不能在枚举类中强制执行,因为该执行具有spring依赖项。

gojuced7

gojuced71#

我认为你在编译时没有选择来执行你的策略。我建议创建一个接口(类似 DateTypeAction )使用单一方法(例如 action() )然后是一个工厂,它根据您的 DateType (类似于 DateTypeActionFactory.getDateTypeAction(DateType dateType) ). 在初始化阶段,可以运行datetype的所有值( DateType.values() )并检查 DateTypeAction 在你的 DateTypeActionFactory 对于每个值。如果发现一个或多个值缺少实现,则抛出一个异常,并显示一条错误消息,告诉您缺少实现,并且无法启动应用程序。这似乎是一个合理的模式。
顺便说一句,如果您使用这种模式,我有一个建议:我编写了一个名为mgntutils的开源java库,它提供了一个简单的框架(非常适合与spring一起使用),该框架具有自填充工厂模式。i、 您可以创建一个接口和一个工厂扩展库提供的父类,然后您的接口的每个实现将自动插入到您的工厂预定义的名称。我用了很多次,觉得很方便。下面是描述整个库的文章的链接:mgntutils开源java库,具有堆栈跟踪过滤、静默字符串解析、unicode转换器和版本比较。查找段落
生命周期管理(自示例化工厂)
对于功能的简短解释。在这里,您可以了解该特性的全部思想:在springframework中对“孤立”bean的非侵入式访问。这两篇文章也解释了从何处获取库,但这里有直接的链接:maven中央存储库和github。该库附带了编写良好的javadoc

niwlg2el

niwlg2el2#

尽管我怀疑这在编译时会受到限制。实现类似功能的一种可能更简洁的方法是使用 switch 在这里:

switch (x.getDateType()) {
    case MONDAY: // do something
        break;
    case SUNDAY: // do something
        break;
    default:
        throw new CustomException("No implementations yet for :" + x.getDateType()); 
}
ifmq2ha2

ifmq2ha23#

真正的答案是:不要这样做。
如果您有一些“类型”,并且您知道随着时间的推移,这个“类型”将看到新的化身,需要不同的行为,那么答案就是使用抽象类和多态性。
不管您使用if/else链还是switch语句:您的想法是:

if (someObject.getSomething() == whatever) { then do this } else { that }

这是坏习惯!
如果有的话,您应该在工厂中使用这样的switch语句来返回不同的子类示例,然后对这些对象调用“common”方法。
您当前的方法是a)外部化关于内部状态的知识,b)以多种方式强制依赖关系。
这就是意大利面代码的开始!最好退一步,考虑更多的面向对象的方法来解决这个问题!

t3irkdon

t3irkdon4#

枚举是用来保存编译时(静态)最终值的,所以动态地添加更多的值是不可能的(只是把它放在那里)。至于问题的另一部分,正如@nullpointer所指出的,最好使用 switch 条款。除了提高代码清晰度外,如果存在没有 case 为它们声明的语句(即 default )

qij5mzcb

qij5mzcb5#

nullpointer选项的另一种选择是将该逻辑放在enum本身中,假设这在您的设计中是有意义的(如果该责任可以由day类型enum承担)。

public enum DayType {
    SUNDAY {
        @Override
        void processSomeAction(Object input) {
            super.processSomeAction(input);
            // process action with SUNDAY-specific logic
        }
    },

    MONDAY;

    //can be made abstract if there's no default implementation
    void processSomeAction(Object input) {
        // process action with default logic
    }
}

这将确保提供特定于某一天的实现的需求对于更改 DayType .
打电话的人只需要:

x.getDateType().processSomeAction(inputIfApplicable);
xmq68pz9

xmq68pz96#

可以创建一个接口,该接口将由枚举类实现。在这种情况下,所有枚举都必须在接口中实现方法。

public enum DateType implements DateTypeInterface {

    SUNDAY {
        @Override
        public void checkCondition() {
            System.out.println("Implement Sunday logic");
        }
    },
    MONDAY {
        @Override
        public void checkCondition() {
            System.out.println("Implement Monday logic.");
        }
    }
}

public interface DateTypeInterface {

     public void checkCondition();
}
i2byvkas

i2byvkas7#

我也不确定按用户设计扩展枚举是否是个好主意。它是静态的,正如@garikai所说。这将导致代码气味。
如果你想有一个简单的选项,扩展Map从枚举到函数我会建议 Map<DateType, Function> map = new EnumMap<DateType, Function>(DateType.class); 然后使用 getOrDefault 以确保您将获得任何输出。

pod7payv

pod7payv8#

这个答案扩展了其他一些促进多态性使用的答案。
为了避免在某个地方出现every growing switch/conditional,我通常会在接口中添加一个标识方法:

public enum Day {
    SUNDAY, MONDAY
}

public interface DayProcessor {

    Day day();

    // I don't know what Days are supposed to do exactly
    Object process(Object input); 
}

然后我用所有可用的 DayProcessor spring引入的实现:

@Component
public class DayProcessorFactory {

    @Autowired
    private List<DayProcessor> dayProcessors;

    public DayProcessor create(Day day) {
        for (DayProcessor dayProcessor: dayProcessors) {
            if (dayProcessor.day().equals(day)) {
                return dayProcessor;
            }
        }
        // DayNotFoundException extends RuntimeException
        throw new DayNotFoundException(String.format("No DayProcessor found for day %s", day));
    }
}

这是战略模式的一种形式。
列出所有日期的另一种方法是枚举它们(但在创建新的日期时,必须更新列表):

private DayProcessor[] dayProcessors = new DayProcessor[] {new MondayProcessor(), new SundayProcessor()};

相关问题