15

我读了 Effective Java 并且那里说单例最好使用enum.

这种方法在功能上等同于公共字段方法,只是它更简洁,免费提供序列化机制,并提供针对多次实例化的铁定保证,即使面对复杂的序列化或反射攻击。虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单例的最佳方式。

尽管如此,这似乎是实现动态序列化和真正的单实例的权衡,但是您失去了经典单例的更友好的 OOP 方法。枚举不能被继承,只能实现一个接口,如果你想提供一个骨架类,你需要创建一个帮助类。

那么,除了上述原因之外,我们为什么要接受枚举作为单例的最佳实现呢?

4

3 回答 3

16

枚举不能被继承

它是单例枚举中最好的部分之一。

如果你可以从单例继承,它就不再是单例了。

于 2012-08-06T21:03:46.610 回答
16

这似乎是实现动态序列化的权衡

对我来说,写类似的东西要简单得多

enum Singleton {
    INSTANCE;
}

如果您需要编写更多代码或引入复杂性,那么就这样做,但恕我直言,这很少需要。

你失去了经典单例的更友好的 OOP 方法。

我发现使用字段更简单。

枚举不能被继承,

没错,但拥有多个单身人士本身就是值得怀疑的。枚举可以从允许您将一种实现交换为另一种实现的接口继承。

如果你想提供一个骨架类,你需要创建一个辅助类

助手类没有任何状态。骨架类可能具有某种状态,在这种情况下您需要委托。

顺便说一句:您可以enum用于帮助类

enum Helper {;
    public static my_static_methods_here;
}

为什么我们应该接受枚举作为单例的最佳实现

我会遵循YAGNI原则。只开发你需要的东西,而不是你想象的你可能需要的东西。

于 2012-08-06T16:38:22.347 回答
11

前段时间在 stackoverflow 上也有过类似的讨论:Java 中实现单例模式的有效方法是什么?

接受的答案提供了关于该主题的良好链接:

Joshua Bloch 在 Google I/O 2008 上的Effective Java Reloaded演讲中解释了这种方法:链接到视频。另请参阅他的演示文稿的幻灯片 30-32 ( effective_java_reloaded.pdf ):

要点是很难编写一个真正的单例。枚举值保证只存在一次,如Java 语言规范 §8.9中所定义:

枚举类型除了由其枚举常量定义的实例外,没有其他实例。

于 2012-08-06T16:39:24.577 回答