java中的單例設計模式詳解

設計模式:對問題行之有效的解決方式,其實就是一種思想。

1.單例設計模式。

解決的問題:就是可以保證一個類在內存中的對象唯一性。
比如對於多個程序使用同一個配置信息對象時,就需要保證該對象的唯一性。

  • 如何保證對象唯一性?
    1.不允許其他程序用new創建該類對象。
    2.在該類創建一個本類實例
    3.對外提供一個方法讓其他程序可以獲取該對象。

  • 步驟:
    1.私有化該類構造函數
    2.通過new在本類中創建一個本類對象。
    3.定義一個公有的方法,將創建的對象返回。

例如:(將下面的程序改爲單例設計模式)

public class Dmo10 {
    public static void main(String[] args) {
        Test t1 = new Test();
        Test t2 = new Test();
        t1.setNum(10);
        t2.setNum(20);
        System.out.println(t1.getNum());
        System.out.println(t2.getNum());
    }
}

class Test {
    private int num;

    public void setNum(int num) {
        this.num = num;
    }

    public int getNum() {
        return num;
    }
}
結果:
10
20

改變之後

public class Dmo10 {
    public static void main(String[] args) {
        Test t1 = Test.getInstance();
        Test t2 = Test.getInstance();
        t1.setNum(10);
        t2.setNum(20);
        System.out.println(t1.getNum());
        System.out.println(t2.getNum());
    }
}

class Test {
    private int num;

    private static Test t = new Test();
    private Test() {}

    public static Test getInstance() {
        return t;
    }
    public void setNum(int num) {
        this.num = num;
    }

    public int getNum() {
        return num;
    }
}
結果:
20
20
  • 單例設計模式有兩種方式:餓漢模式和懶漢模式

餓漢模式:類加載的時候對象就已經存在,餓漢式是線程安全的,在類創建的同時就已經創建好一個靜態的對象供系統使用,以後不再改變。

public class Single {

    private static Single s=new Single();
    private Single(){

    }
    public static Single getInstance(){
        return s;
    }
}

懶漢模式:類加載的時候對象還不存在,就是所謂的延遲加載方式,需要時再進行創建,懶漢式如果在創建實例對象時不加上synchronized則會導致對對象的訪問不是線程安全的。

public class Single {

    private static Single single = null;

    private Single() {

    }

    public static Single getInstance() {
        if (single == null) {
            single = new Single();
        }
        return single;
    }
}

以上懶漢式單例的實現沒有考慮線程安全問題,它是線程不安全的,併發環境下很可能出現多個Singleton實例,要實現線程安全,有以下三種方式,都是對getInstance這個方法改造,保證了懶漢式單例的線程安全,如果你第一次接觸單例模式,對線程安全不是很瞭解,可以先跳過下面這三小條,去看餓漢式單例,等看完後面再回頭考慮線程安全的問題:

1、在getInstance方法上加同步

public static synchronized Single getInstance() {  
         if (single == null) {    
             single = new Single();  
         }    
        return single;  
}  

2、雙重檢查鎖定

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

3、靜態內部類

public class Single {    
    private static class LazyHolder {    
       private static final Single INSTANCE = new Single();    
    }    
    private Single (){}    
    public static final Single getInstance() {    
       return LazyHolder.INSTANCE;    
    }    
}    

這種比上面1、2都好一些,既實現了線程安全,又避免了同步帶來的性能影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章