自Java 5以来最好的单例模式

3
自Java 5以来,最好的创建单例的方法是使用单元素枚举类型。
例如:
public enum SuperSingleton implements Zooma{
    INSTANCE;

    /**
     */
    public void fightTheBattle(){
        System.out.println("I am fighting the battle!!!");
    }

    @Override
    public void runningWild() {
        //This is method implemented from the Zooma interface.      
    }
}

根据Joshua Bloch的说法,单元素枚举类型singleton更加简洁,提供了免费的序列化机制,并且提供了针对多次实例化的坚固保护。
我可以理解它更加简洁并提供了针对多次实例化的坚固保护,但是它如何提供免费的序列化机制呢?
这是因为单例模式作为一个枚举类型获得了这个特性。

2
+1 虽然我认为单例模式是由“敌人”创造出来的,引用布什先生的话。 - Augusto
1
答案就在API中。 - mre
1
请查看此问题:https://dev59.com/4HVD5IYBdhLWcg3wJIEK - CoolBeans
1
好的,那很明显。谢谢大家。 - Koekiebox
1
我喜欢枚举 - 但你的Singleton将无法再继承。请参阅https://dev59.com/FOo6XIcBkEYKwwoYTSsu#5843931 - simpatico
我不同意JB的观点,因为他自己与自己的观点不一致。例如,他说“不要使用接口来声明常量”,并给出理由:“常量使用不是接口,它产生语义不匹配和噪音,并且获得的语法糖(无需使用static final等)不值得”。他在EJ2中多次使用类似的论点...类比地,人们会说“不要使用枚举来声明单例类;单例不是enum-它产生语义不匹配和噪音,并且获得的语法糖不值得”。 - user719662
3个回答

3

是的,枚举类型都是继承自Enum,该类实现了Serializable接口。


哇,听起来很危险。这意味着,如果单例具有某种状态,并且在某些时刻被持久化两次,那么这些对象的反序列化可能是不可预测的,而且单例可能会表现出意外的行为。 - Augusto
5
@Augusto:枚举通常不应该有状态。如果让它们具有状态,可能会在各种方面带来麻烦。 - ColinD
1
但是你所说的是序列化逻辑中的错误,而不是序列化本身的支持。单例模式定义上只能被实例化一次,这意味着一个正确的序列化策略只会将其持久化一次或在多次持久化时进行覆盖。 - Mike Yockey
1
@ColinD 百分之百同意,但有些单例需要维护状态... 我想我想说的是 ENUM 解决方案可能不是最好的解决方案,但在某些情况下是一个好的解决方案。 - Augusto
1
@Augusto:通常情况下,对于有状态的对象或者你可能不想在测试中使用的对象,使用静态实例单例模式都是一个不好的主意,无论你是否使用枚举。然而,对于许多简单、无状态的单例用途,枚举单例是一个不错的选择。 - ColinD
显示剩余3条评论


1

我不是100%确定,但我认为如果您对序列化的单例进行反序列化超过一次,可能会得到多个实例。枚举实例将始终保持单例。

因此,您将获得比仅实现序列化更多的“序列化”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接