在Java中实现单例模式

时间:2010-01-05 20:36:42

标签: java singleton

任何人都可以提供单例模式的示例并解释为什么它们是必要的吗?

6 个答案:

答案 0 :(得分:31)

在走单身路线之前,重新考虑一下。你真的需要一个单身人士吗?如果你在需要实现单例时要求场景,那是因为对它们的需求并没有真正表达出来。你最好不要在你的代码库中引入单例,因为跟随设计模式感觉很酷。

Clean Code Talks - Global State and Singletons

Once Is Not Enough

Performant Singletons

然而,真正值得了解的是Dependency Injection

现在,如果你真的想用Java实现单例,我会推荐Joshua Bloch的"Effective Java"方法来实现它们:

public class Singleton
{
  public static Singleton getInstance() {
    return SingletonHolder.instance;
  }

  private Singleton() {}

  private static final class SingletonHolder {
    static final Singleton instance = new Singleton();    
  }
}

JLS保证JVM在有人调用getInstance();之前不会初始化实例

最后一点,Double Checked Locking Pattern is broken in Java up to Java 5The Java 5 memory model makes the DCL pattern thread safe but it makes it slower than the SingletonHolder class method while the original intent was performance optimization

编辑:正如@Luno指出的那样,since the second edition of the book, the preferred way is:

  

从1.5版开始,实现单例的第三种方法。只需使用一个元素制作枚举类型:

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;

    public void leaveTheBuilding() { ... }
}
  

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

答案 1 :(得分:2)

基本上,在Java中,您通过为类提供私有的无参数构造函数(private MyClass())来实现单例,并静态(或延迟)初始化由静态{{1返回的类的单个实例方法。

如果您希望整个应用程序中只有一个类的实例,则可以使用此方法。

答案 2 :(得分:1)

danben对单身人士有一个非常好的总结,所以我不会重复它。

就用途来说,单身人士往往是全局变量的薄弱实现(这是一个坏主意)。它们可用于消息路由器或管理器类(以及其他内容)。

答案 3 :(得分:0)

Simply Singleton

'JavaWorld'

如果您真的想进入战壕,请先阅读groups或Google上的“静态与单身人士”。总是一个热门话题至少可以说!

答案 4 :(得分:0)

当你想要抽象出国家的存在时,一个经常被低估的单身人才是好的地方。一个例子是随机数发生器。在抽象层次上,它只生成随机数,并且没有调用者需要关注的任何状态。但是,在实施层面,涉及到国家。另一个是当函数缓存结果或中间计算时,但您想要从调用者隐藏此详细信息。

这里有一个重要的权衡。如果你制作像这些单例的东西,你减少了函数调用者必须关心的实现细节量,从而减少了那个方向的耦合。然而,与此同时,你强烈地将你的函数耦合到单例对象,使其更难测试等。关于是否使用单例的决定应该基于你关心减少耦合的方向来做。

答案 5 :(得分:0)

假设办公室中只有一台打印机,您需要确保打印机类只有一个实例

printer{
private static printer instance =null;
private printer(){}
public static printer getinst(){
if( instance==null){
instant = new printer();

}
return instance;


}


}

中的

printer v=printer.geti();