单例模式

  单例模式的定义:确保一个类只有一个实例,并提供一个全局的访问点。

  在应用中,有些对象我们其实只需要一个,例如线程池之类的对象。如果这类对象产生过多不仅浪费资源还有可能引发其它异常。如果只需要达到只存在一个实例这个要求,我们只需要定义一个全局静态变量,然后约定大家都使用这个变量就可以了。的确也是这样的,但是如果有更好的办法能达到只有一个实例,并且带来更多的便利(如避免一开始就创建这个对象),我们是很乐意学习的。

  单例模式共分为三种:懒汉式单例、饿汉式单例、登记式单例。

饿汉式单例

  它只有在第一次请求实例时才会去创建。类加载的时候不需要创建,并且第一次创建以后都不需要再创建。

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

  这种单例很简单,但有个缺点就是:无论这个类是否被使用都会创建这个实例。

懒汉式单例

  这个懒汉式单例,算是对上述饿汉式单例的一个优化。它把对象的创建延迟至使用它的时候。

public class Singleton {
   private static Singleton instance = null;
   
   private Singleton() {}
   
   public static Singleton getInstance() {
      if (instance == null) {
         instance = new Singleton();
      }
      return instance;
   }
}

  但这种方式,在多线程下是不安全。比如当两个线程同时进入instance == null的判断,那么就会创建两个Singleton对象。要保证这个类的线程安全也很简单,只需要给getInstance方法加上同步锁就行了。

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

  但通常只有在第一次判断instance == null的时候才会出现不安全性,如果对整个方法加锁,则会产生很多不必要的开销。要避免这种开销,我们只需要在进入instance == null的时候才加锁。

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

登记式单例

  上述饿汉式和懒汉式单例都把构造方法都私有了,它是不能被继承的。登记式单例就是为克服这一缺点而设计的。

  它会有一个实例池,如果没有会先创建并放到池中再返回实例,如果实例池中存在,则直接从池中取出来。

public class Singleton {

   private static Map<String, Singleton> instance_pool = new HashMap<String, Singleton>();
   static {
      Singleton instance = new Singleton();
      instance_pool.put(Singleton.class.getName(), instance);
   }

   protected Singleton() {
   }

   public static Singleton getInstance(String name) {
      if (name == null)
         name = Singleton.class.getName();
      if (instance_pool.get(name) == null) {
         try {
            instance_pool.put(name, (Singleton) Class.forName(name).newInstance());
         } catch (InstantiationException e) {
            e.printStackTrace();
         } catch (IllegalAccessException e) {
            e.printStackTrace();
         } catch (ClassNotFoundException e) {
            e.printStackTrace();
         }
      }
      return instance_pool.get(name);
   }
}

 

 

    

posted @ 2012-07-18 21:33  zhangchaozheng  阅读(226)  评论(0编辑  收藏  举报