这是一个更多的设计问题。首先,我有一个枚举:
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种这样的方法。
但我有一种感觉,我弄乱了我的枚举。这被认为是不好的设计实践,将业务逻辑特定于不同的枚举类型中的常量特定方法吗?如果我宁愿实现一个接口,并在那里定义方法,并让所有枚举常量实现它们会有什么不同?当然,我必须在那之后到处使用接口引用,但我要看看它是否适用于hibernate映射。目前我使用@Enumerated(EnumType.String)
将枚举常量存储为实体的一部分。所以,我希望另一种方法不要太多地影响这个部分,即结束行为应保持不变。
你怎么说?我应该遵循哪种方法?如果你能想到,我愿意接受任何其他更好的选择吗?
答案 0 :(得分:1)
关于使你的枚举实现一个接口vs扩展每个枚举值的模板方法,我坚持模板方法,因为,正如你所说,不会有任何其他枚举或类实现这些方法。 (如果你有许多需要履行合同的枚举或类,那么实现一个接口是有意义的,但似乎并非如此)。
我个人认为枚举是一些有一些限制的类(即它们是最终的和无状态的),但有些人认为以这种方式使用枚举 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
实体参与的每个关联的获取策略。