Single-Element Enum Type Singleton真的是一个广泛采用的好主意吗?

时间:2010-06-23 16:58:49

标签: java design-patterns

Josh Block的 Effective Java (使用私有构造函数或枚举器强制执行Singleton属性)的第3项提到“虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单身人士的最佳方式。“

示例:

   public enum Elvis {
       INSTANCE;
       private final String[] favoriteSongs =
           { "Hound Dog", "Heartbreak Hotel" };
       public void printFavorites() {
           System.out.println(Arrays.toString(favoriteSongs));
       }
   }

接下来:“这种方法在功能上等同于公共字段方法,除了它更简洁,免费提供序列化机制,并提供防止多个实例化的铁定保证,即使面对复杂的序列化或反射攻击。“

我看到的最大的负面影响是:不是枚举不应该具有可变状态吗?使用具有状态的Singleton似乎很常见。

自出版日期(2008年第2版)以来,这种模式实际上变得更加普遍吗?

5 个答案:

答案 0 :(得分:10)

虽然枚举通常不会被赋予可变状态,但这个事实是基于如何使用枚举的假设。虽然这些假设通常都有,但它们并不总是如此,并且他们不这样做的情况就是创建一个单身人士。

虽然它不是枚举的最常见用法,但拥有可变状态的枚举是完全合法的,尽管你可能想在你的代码中指出这个事实,所以任何其他可能正在查看它的程序员都没有得到困惑。

至于这种设计模式的受欢迎程度,我经常看到它,但并不是说它已经变得“普遍”了。

答案 1 :(得分:8)

(这个答案假设“强制”单身人员真的你想要什么,而不是你的DI框架管理的事实上的单身人士(例如Guice的@Singleton),这是可能更经常是正确的想法。)

将您的问题分解为两个:它是否真的被广泛采用?不,没有它应该的那样广泛。这是个好主意吗?是的!

Java枚举是一个只能有一组固定N个实例的类,这些实例在源代码中是硬编码的。

单例是一个只能有一组固定N个实例的类,它们在源代码中是硬编码的。并且N == 1。

就这么简单!

答案 2 :(得分:3)

枚举可以具有可变状态。这通常不是一个好主意,因为枚举的本质是要有一个类型Y的X版本,其中X大于1,因此围绕状态(除了使用字段/属性)之间的杂耍变得有点像每个方法的噩梦需要考虑所有X枚举常量的所有可能状态。

但是如果你打算定义一个只有一个常量的枚举;您可以简单地将该单个常量视为普通对象,并进行随附的所有假设。 IOW:X版本的状态消失了,因为X现在是1.

答案 3 :(得分:1)

没有enum不应该具有可变状态。静力学通常不应该是可变的。单身人士只是模糊可变静力学的方法。 (实现接口的无状态对象是另一回事。)

答案 4 :(得分:-4)

这不是一个好主意。

它强制你的类继承具体的类Enum。这会污染您的类型层次结构。

INSTANCE的类型必须正好Elvis;它不能是Elvis的某个子类型。

更一般地说,您无权自由选择实例的实例化方式。

语法方面,打印真的太多了吗?

public class Elvis {
    static public Elvis INSTANCE = new Elvis();