设计模式:单例模式

  单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例,并提供一个全局访问点

  使用单例模式的目的在于尽可能节约内存空间,减少GC的消耗。

  一个类能否成为单例,主要就是说这些类在应用中如果有两个以上实例会引起一定错误。

  首先看下一个最原始的单例模式

public class Singleton {

    //一个静态的实例
    private static Singleton singleton;

    //私有化构造函数
    private Singleton(){}

    //给出一个公共的静态方法返回一个单一实例
    public static Singleton getInstance(){
        if (singleton == null) {
            singleton = new Singleton();
        }
        return singleton;
    }
}

  上面最原始的代码主要通过静态实例+私有化构造方法来创建的。但是如果考虑到多线程的话,上面的代码就不行了,那么有人想到用synchronize,

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

做法是很简单,但是会造成很多无谓的等待,是非常不好的设计。其实,将上面的更改下就会好多了,如下:

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

在只有实例为null的情况下才会去创建同步,大大减少了同步时间,而在同步内的if判断是因为,如果线程A和线程B都在synchronized外判断了singleton为null,然后A获取了线程锁然后将singleton实例化了,最后释放锁,这时,B拿到了锁,而如果没有在此判断singleton是否为nul的话,B就会在创建一个实例了。

虽然上面的已经基本解决了在多线程下的单例模式,但考虑其他方面,上述方式也存在一定局限。下面介绍最终两种方式:饿汉模式和懒汉模式

  饿汉模式:系统中对象只有有一个唯一的实例,将对象的创建交给成员变量,空间换时间,一开始就创建实例。但容易造成资源的浪费,不过也没什么影响。

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

  懒汉模式(推荐):用到实例时候再初始化对象,使用静态内部类实现可以避免多线程下的安全问题。

public class LazySingleton {
    private static class Inner{
        private static LazySingleton instance = new LazySingleton();
    }
    private LazySingleton(){}
    public static LazySingleton getInstance(){
        return Inner.instance;
    }
}

 

   下一节:命令模式

posted @ 2017-02-21 09:55  哀&RT  阅读(93)  评论(0编辑  收藏  举报