Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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 为什么enum是单例的最佳实现?_Java_Design Patterns_Enums_Singleton - Fatal编程技术网

Java 为什么enum是单例的最佳实现?

Java 为什么enum是单例的最佳实现?,java,design-patterns,enums,singleton,Java,Design Patterns,Enums,Singleton,我读过《有效的Java》,书中说最好使用enum实现单例 此方法在功能上等同于公共字段方法,只是它更简洁,免费提供序列化机制,并提供了防止多个实例化的铁性保证,即使面对复杂的序列化或反射攻击也是如此。虽然这种方法还没有被广泛采用,但单元素枚举类型是实现单例的最佳方式 尽管如此,这似乎是实现动态序列化和真正的单实例的一种折衷,但是您失去了经典单实例的更友好的OOP方法。枚举不能被继承,只能实现一个接口,如果你想提供一个骨架类,你需要创建一个助手类 那么,除了上述原因之外,我们为什么要接受enum作

我读过《有效的Java》,书中说最好使用
enum
实现单例

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

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

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

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

对我来说,写这样的东西要简单得多,简洁得多

enum Singleton {
    INSTANCE;
}
如果您需要编写更多的代码或引入复杂性,那么就这样做,但IMHO很少需要这样做

您将失去经典单例中更友好的OOP方法

我发现使用字段更简单

无法继承枚举

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

如果要提供骨架类,则需要创建帮助器类

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

顺便说一句:您可以对助手类使用
enum

enum Helper {;
    public static my_static_methods_here;
}
为什么我们应该接受enum作为单例的最佳实现


我会遵循这个原则。只开发您需要的,而不是您想象中可能需要的。

不久前在stackoverflow上也有类似的讨论:

公认的答案提供了有关该主题的良好链接:

Joshua Bloch在谷歌I/O 2008的演讲中解释了这一方法:。也看到 他的演示文稿的幻灯片30-32():

主要的一点是,编写一个真正的单例是相当困难的。枚举值保证只存在一次,如中所定义:

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

无法继承枚举

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


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

你说的是什么样的“骨架类”?我不记得为了创建一个单例而对另一个非对象类进行子类化的每一个子类——它几乎总是实现一个接口。(我并不是说这不会发生——我只是不记得做过。)真正的问题是,为什么你一开始就要求单身?如果您确实需要它,那么一个单身汉将如何扩展另一个类?那班学生也是单身吗?如果没有,这是如何工作的?如果是,如果其他人也扩展了它,会发生什么?您将有两个单例基类的实例。这可能很有用。Singleton是一种严重不推荐的反模式,我认为它唯一合理的用途是实现常量,枚举可以很方便地实现它。@sa_vedem我猜他指的是除java.lang.Object之外的任何类。你在哪里找到这句话的?枚举值保证只存在一次。有官方文档吗?@YanKhonski这是Java语言规范的一部分::“枚举类型除了由其枚举常量定义的实例外,没有其他实例。尝试显式实例化枚举类型(§15.9.1)是编译时错误。”我相应地更新了答案。