1. 程式人生 > >單例模式一二三

單例模式一二三

out 支持 turn pos 系統 mod 單例 sys clas

單例模式幹的事情非常easy,就是要保證某一個對象全局唯一。


對嗎? 對不正確要看標準
單例模式(Singleton Pattern):確保某一個類僅僅有一個實例,並且自行實例化並向整個系統提供這個實例。
這個類稱為單例類。它提供全局訪問的方法。單例模式是一種對象創建型模式。
看來我之前定義的不全對。
第一 保證類僅僅有一個實例
第二 類本身自己實例化(意思就是不能讓別的類來new自己)
第三 提供全局訪問的方法
OK 那我如今寫出第一種Singleton

第一種Singleton

public class Singleton{
    private static Singleton sl;
    private Singleton(){
       System.out.println("初始化");
    }

    public static Singleton getInstance(){
    if(sl==null)
         sl=new Singleton();
     return sl;
    }
    
    public static void main(String[] args){
        Singleton sl=Singleton.getInstance();
        Singleton sl2=Singleton.getInstance();
    }
}
執行結果是顯示一個初始化
可是這裏存在一個問題 假設多個線程同一時候執行這段代碼,當第一個線程執行到sl=new Singleton()時(這一句還沒有執行),第二個線程檢查sl還是為null的,此時第二個線程也進來了... 然後就有多個對象了。

所以有

另外一種Singleton

/***
 * 餓漢模式
 */
public class Singleton2{
    private final static Singleton2  sl2=new Singleton2();
    private Singleton2(){
        System.out.println("初始化");
    }
    public static Singleton2 getInstance(){
        return sl2;
    }
    public static void main(String[] args){
        Singleton2 sl2=Singleton2.getInstance();
        Singleton2 sl3=Singleton2.getInstance();
    }
}
這樣的單例模式,我們在類載入的時候,就把類變量new出來。這樣的方式我們稱之為餓漢模式。
首先餓漢問題攻克了上面的線程問題。我最開始載入的時候就有了類變量了而且還僅僅有一個,自然不會存在線程問題了。
但這裏有個性能問題,無論我用不用這個單例類,它總會被載入內存中,因此性能是個問題。


上面說了這個模式叫餓漢模式,那自然有非餓漢模式(術語叫懶漢模式)。只是在這裏我不太想和大家聊懶漢模式,太復雜,且不怎麽用。
那有沒有一種單例,既能解決第一個的線程問題,同一時候保持性能(事實上另外一種餓漢模式就不錯了,就那一個類,能拖多少性能?就算有10個,100個也不是太多)呢?並且也不像我說的那個"懶漢模式"那麽復雜呢?


答案是肯定的。

有!

內部類模式

public class Singleton3{
    private static class hold{
        private  final static Singleton3 sl3=new Singleton3();
    }
    private Singleton3(){
    System.out.println("初始化");
    }
    public static Singleton3 getInstance(){
          return hold.sl3;
    }
    public static void main(String[] args){
             Singleton3 sl3=Singleton3.getInstance();
         Singleton3 sl4=Singleton3.getInstance();
         System.out.println(sl3==sl4);
    }
}
關於內部類與static,final的分析,我們這裏臨時不講。
內部類的方式攻克了上面所提的幾個問題。


但也引出了一個不是問題的問題

內部類是java支持的,可是在別的語言中,不一定。

參考資料

http://blog.csdn.net/lovelion/article/details/7420883

單例模式一二三