Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 枚举对象是否应该是无状态的?_Java_Oop_Enums - Fatal编程技术网

Java 枚举对象是否应该是无状态的?

Java 枚举对象是否应该是无状态的?,java,oop,enums,Java,Oop,Enums,通过设计,java中的枚举常量是单例的,为了并行使用,我通常创建无状态枚举实例,并根据需要使用方法参数注入数据 例如: 目前,我正在创建一个REST服务,该服务具有操作(使用策略模式的变体作为枚举实现) 现在我想收集一个操作被调用的频率和成功的频率等数据 在使用enum实例时,我可以在外部保存状态,但似乎应该在操作中保存状态,因为操作应该包含自己的状态 现在我的一般问题是: 有状态枚举实例(除了并发问题)是一个糟糕的设计吗?我认为它违反了最小惊讶原则 人们期望枚举能像最初设计的那样被普遍使用——

通过设计,java中的枚举常量是单例的,为了并行使用,我通常创建无状态枚举实例,并根据需要使用方法参数注入数据

例如:

目前,我正在创建一个REST服务,该服务具有操作(使用策略模式的变体作为枚举实现)

现在我想收集一个操作被调用的频率和成功的频率等数据

在使用enum实例时,我可以在外部保存状态,但似乎应该在操作中保存状态,因为操作应该包含自己的状态

现在我的一般问题是:


有状态枚举实例(除了并发问题)是一个糟糕的设计吗?

我认为它违反了最小惊讶原则


人们期望枚举能像最初设计的那样被普遍使用——作为常量或令牌,而不是作为带有状态的通用类。

这似乎是枚举的一个不好的用途——为什么不为每个操作使用一个带有新子类的基抽象类呢?

是的。我说的“是”是指“永远”


如果您想对调用的操作数进行统计,请实现一些可观察性。

任何形式的可变静态都是一种罪恶。(好吧,你可能会逃脱不泄漏的缓存,一些懒惰的初始化和记录形式。)

我完全同意mparaz的观点,即它违反了最少惊讶的原则。人们期望枚举是常量

几乎可以肯定,您可以通过以下方式解决日志记录问题:

DO_THIS() {
  public Result doSomething(Object theData) {
    MyUtilClass.doSomething(Object theData);
  }
}
并将您的日志记录放在另一个类中


然而,如果你不能解决这个问题,最小惊讶原则是一个指导原则;如果您对该类的用户给出了足够的警告,说明发生了什么,您就可以违反它。确保Enum声明包含一个大的通知,说明它是可变的,并准确地描述了可变性是什么。Enum应该仍然有效;它对单个实例进行引用比较,以测试枚举值。

每次创建可变枚举时,都会有一只小猫死去。救救小猫

有状态枚举是一种矛盾修饰法,甚至是一种反模式

枚举是项的集合,是该集合中所有项的完整有序列表。该术语在数学和理论计算机科学中常用,指集合中所有元素的列表。在统计学中,使用术语分类变量,而不是枚举。枚举的精确要求(例如,集合是否必须是有限的,或者列表是否允许包含重复)取决于数学分支和工作环境

枚举有有限数量的值,这些值应该是常量,而它们是常量

然而,它们是“第一类”Java对象这一事实完全违背了枚举的意图或精神


如果需要任何类型的状态,枚举(如前所述)应该保持方面中的状态,或者有问题的枚举至少应该保持对保持状态的委托类的引用。理解“关注点分离”将有所帮助。

有一种情况可能会证明这一点。 枚举可以实现一个接口,通常需要考虑允许您创建的特定用例 在运行时/以动态方式公开“其他类型的枚举类”,以某种方式命名

这意味着可以强制枚举“singleton”实例实现一些可变的预期方法签名(作为setter),当然,您仍然可以使用空代码或NotSupportedException隐藏这些签名


幸运的是,接口中的最终方法不允许改变状态。这将是我能想到的唯一“可以理解”的情况。

与此相反,枚举成员实际上是第一类java对象实例,因此它们可以有方法和变量。因此,可能整个枚举设计都有缺陷?我认为Java设计人员使用类来进行枚举的原因是它们允许引用唯一性(换句话说,==可以工作)。理想的情况是使用“符号”之类的东西,但是它们需要JVM支持,而且变化太大了。@mparaz:不,Java设计人员制作了类似枚举的类来允许它们有行为,这是我在C#中错过的Java的唯一语言特性。具有行为的枚举非常棒。因为操作本身是固定的,转换为操作类型和使用工厂对我来说似乎太多开销…我认为您可能过早地进行了优化-使用工厂没有任何问题,事实上会使您的代码更容易测试。我会考虑这一点。目前我的想法是在方法签名中添加一个StateContainer实例……等等。如果您将可观察性添加到枚举,那么您已经使其成为statefull!以当前形式回答不可接受的问题。请提供相关的实证证据!毫无疑问,是的。
DO_THIS() {
  public Result doSomething(Object theData) {
    MyUtilClass.doSomething(Object theData);
  }
}