【问题标题】:Constant specific methods for enum design decision枚举设计决策的常量特定方法
【发布时间】:2015-02-08 16:59:35
【问题描述】:

这更像是一个设计问题。所以首先,我有一个枚举:

enum WageType {
    MONTHLY {
        public int getWageRatePerUnit() {
            return 60000;
        }

        public boolean isPaymentTime(DateTime date) {
            return date.getDayOfMonth() == 29;
        }
    },
    DAILY {
        public int getWageRatePerUnit() {
            return 2500;
        }

        public boolean isPaymentTime(DateTime date) {
            return date.getHourOfDay() == 20;
        }
    };

    public abstract int getWageRatePerUnit();
    public abstract boolean isPaymentTime(DateTime date);
}

现在我有 2 个抽象方法,以及枚举常量中的相应实现。实际场景中包含某种冗长的业务逻辑,我最终得到了 3 或 4 个这样的方法。

但我有一种感觉,我搞砸了我的枚举。这是否被认为是糟糕的设计实践,将特定于不同枚举类型的业务逻辑放在常量特定的方法中?如果我宁愿实现一个接口,并在那里定义方法,然后让所有枚举常量实现它们,那会有什么不同呢?当然,在那之后我将不得不在任何地方使用接口引用,但我必须看看它是否适用于休眠映射。目前,我使用@Enumerated(EnumType.String) 将枚举常量存储为实体的一部分。所以,我希望另一种方法不会对这部分产生太大影响,即最终行为应该保持不变。

顺便说一句,我认为不需要接口,因为我不会拥有一组具有类似行为的单独枚举常量。其他选项可能是某种实用程序类,以处理这些枚举常量。只需将方法传递给它正在处理的枚举类型。

你说什么?我应该遵循哪种方法?如果您能想到,我愿意接受任何其他更好的选择?

【问题讨论】:

  • 你为什么用“休眠”标记这个问题?您是否需要将枚举存储为字符串或表列中的序数值? hibernate和枚举有什么关系?你想在枚举中注入一些 bean 吗?
  • @Magnamag 好吧,我必须将枚举常量作为我的实体的一部分存储在 db 中。目前我正在通过@Enumerated(EnumType.String) 进行操作。因此,如果采用更好的方法,我希望我不必在该部分进行更改(如果需要的话,也不需要太多)。

标签: java spring hibernate design-patterns enums


【解决方案1】:

关于让您的枚举实现接口与为每个枚举值扩展模板方法,我会坚持使用模板方法,因为正如您所说,不会有任何其他枚举或类实现这些方法。 (如果您有许多需要履行合同的枚举或类,则实现接口是有意义的,但情况似乎并非如此)。

我个人认为枚举是具有一些约束的类(即它们是最终的和无状态的),但有人认为以这种方式使用枚举是hacky。我完全不同意,因为我认为使用语言提供的特性是绝对有效的,而模板方法就是这样的特性之一。但是,很高兴知道这种方法在一些保守的环境中会产生阻力。

尽管如此,我确实认为在枚举中使用模板方法会使您的代码非常冗长。如果模板方法的数量和枚举值的数量都很低,并且如果它被授予它们将来不会改变,我只会采用这种方法。

另一方面,您可以通过使用此代码而不是您的代码来实现完全相同的功能:

public enum WageType {
    MONTHLY(60000, 29), DAILY(2500, 20);

    private final int wageRatePerUnit;
    private final int hourOfDay;

    public WageType(int wageRatePerUnit, int hourOfDay) {
        this.wageRatePerUnit = wageRatePerUnit;
        this.hourOfDay = hourOfDay;
    }

    public int getWageRatePerUnit() {
        return this.wageRatePerUnit;
    }

    public boolean isPaymentTime(DateTime date) {
        return date.getHourOfDay() == this.hourOfDay;
    }
}

此代码比您的代码简单得多,并且提供完全相同的功能。但是,您将无法从数据库中检索枚举,因为 Hibernate 找不到它的默认构造函数。

现在,我相信使用可用的语言特性来解决问题是可以的,但是使用它们是因为否则 Hibernate 将不知道如何实现您的枚举...嗯,这就是我所说的 解决方法。

也许您可以将WageType 设为实体并让 Hibernate 照常处理它,并将其关联到其他实体,然后在该实体的方法或实体外部的服务类或某些实用程序中实现您的逻辑课,随你喜欢。请注意,这将导致额外的连接或选择(或者可能是子选择,呃),具体取决于WageType 实体参与的每个关联的获取策略。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2015-08-21
    • 2023-03-04
    相关资源
    最近更新 更多