在Java中使用枚举单例有什么用?

时间:2015-10-02 18:37:49

标签: java design-patterns singleton

当Gang of four引入单例模式时,他们还必须解释,为什么不使用静态类字段和方法。原因是:继承的可能性。对于Java来说它有意义 - 我们通常不能继承类字段和方法。

后来" Effective Java"书出现了。我们现在知道反射的存在破坏了私有构造函数的单例类的奇点。制作真正的SINGLEton的唯一方法是将其作为枚举的单个项目。尼斯。我这样做了一些。

但问题仍然存在:虽然我们不能继承枚举,但这个单身人士的用途是什么?为什么我们不使用这些旧的好静态/类字段和方法?

编辑。感谢@ bayou.io,我发现在https://softwareengineering.stackexchange.com/a/204181/44104中有一个代码可以欺骗枚举,并再次创建枚举单例的两个示例。那里也提到了其他问题。那么,也没有必要使用枚举而不是通常的单例类模式?顺便说一下,到现在为止所提到的所有枚举,也适用于单身人士课程。

4 个答案:

答案 0 :(得分:3)

这个单身人士有什么用?为什么我们不使用这些旧的静态/类字段和方法?

因为var Rep = (function () { angular .module('RepresentativeApp') .controller('Rep', [Rep]); Rep.$inject = ['govtracksvc']; function Rep(govtracksvc) { var model = govtracksvc.searchRole(); return model; } })(); 是一个对象,所以它不仅可以传递,还可以实现接口。

此外,由于我们正在上课,我们可以使用各种类别的不同公共/私人选项。

所以在实践中,我们可以创建一个实现接口的单例,然后在我们的代码中传递它,并且调用代码不是更明智的。我们也可以将enum类包设为私有,但仍将它传递给其他期望接口的包中的其他类。

如果我们使用静态方法版本,那么调用类必须知道这个对象是一个单例,我们的单例类必须是公共的,所以其他类可以看到它并使用它的方法

答案 1 :(得分:2)

"好老式的单身",enum"单身"没有什么特别的错。只是方便 - 它可以节省你需要在每个singelton看起来相同的锅炉电镀代码。

答案 2 :(得分:1)

对我而言,单身人士无论在哪里想要代表同类中独一无二的东西都是有意义的。

例如,如果我们想对 Sun进行建模,则它不能是普通类,因为只有一个Sun。但是,让它从Star类继承是有意义的。在这种情况下,我会选择静态实例,使用静态getter。

澄清一下,这就是我所说的:

public class Star {
    private final String name;
    private final double density, massInKg;  

    public Star(String name, double density, double massInKg) {
        // ...
    }

    public void explode() {
       // ...
    }
}

public final class Sun extends Star {
    public static final Sun INSTANCE = new Sun();

    private Sun() { super("The shiniest of all", /**...**/, /**...**/); }
}

Sun可以使用Star的所有方法并定义新方法。对于枚举(扩展一个类,我的意思是),这是不可能的。

如果不需要为这种继承关系建模,正如你所说,enum变得更适合,或者至少更容易和更清晰。例如,如果一个应用程序每个JVM只有一个ApplicationContext,那么将它作为一个单例是有意义的,它通常不需要从任何东西继承或可扩展。然后我会使用enum

请注意,在某些语言(如Scala)中,单例(object)有一个特殊关键字,它不仅可以轻松定义单例,还可以完全取代静态方法或字段的概念。

答案 3 :(得分:0)

  1. ENUM 单身人士易于撰写。它将占用非常少的代码,这是干净的&如果你与lazy singleton的实现与双重同步块的比较

    ,那就太优雅了
     public enum EasySingleton{
        INSTANCE;
    }
    
  2. ENUM 实例的创建是线程安全的。

  3. ENUM 单身人士自行处理序列化。

    实现Serializable接口的常规单例不再是单例,因为readObject()方法总是像Java中的构造函数一样返回一个新实例。您可以通过使用readResolve()方法并通过替换Singeton

    来丢弃新创建的实例来避免这种情况
    private Object readResolve(){
        return INSTANCE;
    }
    
  4. 看看这个article on singleton