关于java:实现Singleton设计模式的方法

ways to implement the Singleton design pattern

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Efficient way to implement singleton pattern in Java

有人能帮助我理解两种实现设计模式的方法吗?我知道一种方法,那就是让构造函数私有化。谢谢你的指点。


最简单的实现是直接在singleton类的私有字段中声明singleton:

1
2
3
4
5
public class Singleton {
    private static final instance = new Singleton();
    private Singleton() {}
    public Singleton getInstance() { return instance; }
}

其他实现包含在单例的"延迟加载"中:仅当您第一次调用"getInstance"方法时才创建实例。

为了在多线程上下文中保护代码,有各种方法(双重空检查、内部类等)。

通过快速的谷歌搜索,你会发现更多的精确性。


另一个使用volatile关键字的版本。我讨厌易变的关键词。没有理智的人会把这个版本带到教授面前,因为可能的问题是:"volatile到底是做什么的,它是如何工作的?"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Singleton {

    private volatile static Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if(singleton == null) {
            synchronized (Singleton.class) {
                if(singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
  • 是的,它是线程安全的。
  • 是的,我检查了两次singleton是否为空。
  • 是的,它不同于Benoit,因为这个版本延迟地实例化了单例。只有在实际需要实例时(而不是在加载类时),才会创建单例(并同步块)。
  • 是的,它不同于查理的,因为我只同步过一次。创建单例之后,我将不再同步。此外,同步块而不是方法可以减少开销。

注:

  • 它可能不适用于旧版本的Java。如果你的Java版本旧了,升级它。如果你不能的话,就用贝诺特的,那也是安全的。
  • 如果不使用线程,请不要同步,因为它可能会将性能降低100倍,并在删除synchronized关键字后使用charlie的。
  • 请不要演戏。

  • 一种简单的方法是创建一个只包含静态成员的类。这有效地实现了单例模式,不允许类的多个实例。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Singleton {
        private static String m_string;
        private static int m_int;
        static {
            // initialization code...
        }

        public static void foo() {
        }
    }

    当然,类不能作为对象传递给其他方法,但是这对于单例没有意义,因为它们可以直接从代码中的任何地方引用(当然,这是它们最大的缺点,因为它会创建非常不稳定的代码)。


    也可以使用枚举

    1
    2
    3
        public enum Foo {        
        INSTANCE;    
        }


    单例设计模式的一个简单示例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class SingletonPattern
    {
      private static SingletonPattern instance;
      private SingletonPattern()
      { }
    public static synchronized SingletonPattern getInstance(){
      if (instance == null)
      {
        instance = new SingletonPattern();
      }
      return instance;
    }

    public static void main(String arg[])
      {
        System.out.println("The output of two instance:");
        SingletonPattern sp=new SingletonPattern();
        System.out.println("First Instance:"+sp.getInstance());
        sp=new SingletonPattern();
        System.out.println("Second Instance:"+sp.getInstance());
      }
    }

    编辑

    创建单例模式的另一种方法如下:

    1
    2
    3
    4
    5
    public enum SingletonPattern
    {
           INSTANCE;
           // other methods
    }

    枚举只有一个构造函数,程序员不能调用它,因此您不能再创建任何实例,您不必担心序列化问题,因为默认情况下枚举是可序列化的。