Singleton的2个实现

时间:2012-07-31 01:04:44

标签: java design-patterns static singleton

我知道在java中实现单例模式的两种方法,我想知道哪一个更好,为什么。

第一种方式是:

  1. 声明类私有的构造函数
  2. 让类中的所有内容都是静态的 - 基本上类实例本身就是单例
  3. 第二种方式是:

    1. 声明类私有的构造函数
    2. 有一个静态成员来保存单例(可能是该类的一个实例)
    3. 有一个静态的getInstance()方法
    4. 我倾向于认为即使第二种方法是最常见的,第一种方法可能会产生更好的代码可读性,这两种方法在运行时复杂性上看起来同样有效,所以我真的没有理由为什么第二种方法是这样的更常见,被认为是更好的做法...

      启发我!

6 个答案:

答案 0 :(得分:5)

第一种方法不是单身人士。 singleton 是一个类,其中只有一个实例,不多也不少,可以存在。第一件事有时被称为“静态类”,“实用类”或“不可实现的类”。

您可以使用实用类无法完成的“真实”单例执行许多操作。例如,您可以拥有一个实现接口或扩展另一个类的单例;你不能用all-static-methods的东西做到这一点。全静态方法类通常证明没有进行面向对象的设计分析

至于在Java中实现单例模式的方式有多少,实际上有很多有趣的方法,使用不同的语言特性来推迟初始化直到绝对需要:类加载,枚举或只是一个同步块和if

答案 1 :(得分:3)

静态方法阻碍了使用单例的其他类的可测试性。使用实例,您可以替换模拟对象或其他形式的测试双。

答案 2 :(得分:1)

基于对象的单例

的优点
  1. 在任何可能无法想象的情况下,你的“单身人士”会变成非单身吗? 也许你会想要每个线程,每个连接或其他一些分类? 门#2为您留下了未来,无需重写代码。

  2. 你可能有一个单身人士,但你只有一个单身人士的实施吗?一种常见的模式是让工厂方法查看运行时环境,并确定单例提供的“服务”的哪个实现是合适的。公共记录LogFactory是这种单例的示例。

答案 3 :(得分:0)

如果我得到你的问题,那就对了。

为什么这是#2

public class MySingleton {

  static private MySingleton instance=new MySingleton();

  private MySingleton() {}

  static public MySingleton getInstance() { return instance; }

}

优于#1

...对不起,我没有得到第一点...... - >实际上从其他评论中读到了我。我确认,使用静态方法并不意味着你有一个单身人士。所以比较甚至不公平; - /

无论是什么,#2更好的原因是因为多线程。当从静态初始化器初始化单例时,jvm确保只有一个线程实例化该类。

答案 4 :(得分:0)

实现单例模式的方法很少。让我回想一下我读过的一些实现:

  1. 您在问题中提到的第二种方法。 (不是线程安全的)
  2. 开发多线程应用程序时,可能需要使用锁(简单线程安全)

    公共密封班Singleton {     static Singleton instance = null;     static readonly object padlock = new object();

    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
    

    }

  3. 仔细检查锁定

    公共密封班Singleton {     static Singleton instance = null;     static readonly object padlock = new object();

    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                lock (padlock)
                {
                    if (instance==null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    }

  4. 不是懒惰,但不使用锁

    是线程安全的

    公共密封班Singleton {     static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }
    
    Singleton()
    {
    }
    
    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
    

    }

  5. 完全延迟初始化

    公共密封班Singleton {     辛格尔顿()     {     }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }
    
    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }
    
        internal static readonly Singleton instance = new Singleton();
    }
    

    }

  6. 第三种方法在java.Becos中不起作用Java内存模型不能确保构造函数在将新对象的引用分配给实例之前完成。

    希望这会对你有所帮助。

答案 5 :(得分:-2)

也许考虑使用枚举实现单例:

public enum Singleton {
INSTANCE;

public void doStuff() {
    System.out.println("Whoopee");
}
}

并将其称为Singleton.INSTANCE.doStuff()

这在Josh Bloch的Effective Java一书中推荐