The Singleton Pattern

2019-02-11  本文已影响0人  想跳舞的兔子

本篇我们要讲的是单例模式(the Singleton Pattern)
单例模式是旨在创造只被创建一次的对象。

1.模式起源:

首先,让我们探讨以下,该模式是在何种需求下产生的。
当我们需要调用对象时,我们通常会创建一个来使用,但是,对于那些共享的变量,我们不能随意创建,因为多例会使本身应该只有一份的对象变成多份,弄乱程序,我们需要做的努力是,如何获取调用一个对象,且该对象只被创建一次。

2.模式代码进阶:

首先,我们只对于单线程进行思考。
1.不能被随意创建的对象意味着我们需要把public的构造器变成private。
2.因为只有静态类变量/函数可以在不初始化类的条件下依旧可以被调用,所以,我们需要static
3.为了被私有构造函数创建的单个对象被引用,我们需要定义一个static 的类变量,一个调用对象的static类函数.
综上,我们可以得出第一个singleton pattern

public class Singleton{
      private static Singleton uniqueInstance;
      //other useful instance variables here
      private Singleton(){}
      public static Singleton getInstance(){
            if (uniqueInstance == null)
            {  uniqueInstance = new Singleton();}
            return uniqueInstance;
      }
      //other useful methods here
}

当上例纯粹单线程的时候是没有问题的,但是如果在多线程环境,上述代码会出问题。假设,我们有两个线程同时进行到if (uniqueInstance == null) 且当前uniqueInstance确实为null,那么这两个线程会分别创建一个对象,这就会出问题了。为了修正多线程下的这个问题,我们引入synchronized.

public class Singleton{
      private static Singleton uniqueInstance;
      //other useful instance variables here
      private Singleton(){}
      public static synchronized Singleton getInstance(){
            if(uniqueInstance == null)
            { uniqueInstance = new Singleton();}
            return uniqueInstance;
      }
}

引入动态synchronized的代价比较大,我们从下面几个方面来改进多线程:

public class Singleton{
      private static Singleton uniqueInstance = new Singleton();
      private Singleton(){}
      public static Singleton getInstance()
      {  return uniqueInstance;}
}

+我们也可以采用“double-checked locking”来替换synchronized在getInstance()中的使用。

public class Singleton{
      private volatile static Singleton uniqueInstance;
      private Singleton(){}
      public static Singleton getInstance(){   
          if(uniqueInstance == null){
              synchronized(Singleton.class){
                  if(uniqueInstance == null){
                        uniqueInstance = new Singleton()
                  }
              }
          }
          return uniqueInstance;
      }
}

注意:该“double-checked locking”在java版本低于1.4上是不好用的。在JVM上有其他方式来保证同步性,如果你使用JVM而不是java5的话,需要采用其他方式来处理。

上一篇下一篇

猜你喜欢

热点阅读