258、Java基礎35 - 類和對象【單例模式**】 2019.11.16

1、單例模式

  • 單例模式又叫做 Singleton模式,指的是一個類,在一個JVM裏,只有一個實例存在

  • LOL裏有一個怪叫大龍GiantDragon,只有一隻,所以該類,只能被實例化一次

2、餓漢式單例模式

  • GiantDragon 應該只有一隻,通過私有化其構造方法,使得外部無法通過new 得到新的實例。
    GiantDragon 提供了一個public static的getInstance方法,外部調用者通過該方法獲取12行定義的對象,而且每一次都是獲取同一個對象。 從而達到單例的目的。
    這種單例模式又叫做餓漢式單例模式,無論如何都會創建一個實例
  • GiantDragon.java
package charactor;
 
public class GiantDragon {
 
    //私有化構造方法使得該類無法在外部通過new 進行實例化
    private GiantDragon(){
         
    }
 
    //準備一個類屬性,指向一個實例化對象。 因爲是類屬性,所以只有一個
 
    private static GiantDragon instance = new GiantDragon();
     
    //public static 方法,提供給調用者獲取12行定義的對象
    public static GiantDragon getInstance(){
        return instance;
    }
     
}
  • TestGiantDragon.java
package charactor;
 
public class TestGiantDragon {
 
    public static void main(String[] args) {
        //通過new實例化會報錯
//      GiantDragon g = new GiantDragon();
         
        //只能通過getInstance得到對象
         
        GiantDragon g1 = GiantDragon.getInstance();
        GiantDragon g2 = GiantDragon.getInstance();
        GiantDragon g3 = GiantDragon.getInstance();
         
        //都是同一個對象
        System.out.println(g1==g2);
        System.out.println(g1==g3);
    }
}

3、懶漢式單例模式

懶漢式單例模式與餓漢式單例模式不同,只有在調用getInstance的時候,纔會創建實例

  • GiantDragon.java
package charactor;
 
public class GiantDragon {
  
    //私有化構造方法使得該類無法在外部通過new 進行實例化
    private GiantDragon(){       
    }
  
    //準備一個類屬性,用於指向一個實例化對象,但是暫時指向null
    private static GiantDragon instance;
      
    //public static 方法,返回實例對象
    public static GiantDragon getInstance(){
        //第一次訪問的時候,發現instance沒有指向任何對象,這時實例化一個對象
        if(null==instance){
            instance = new GiantDragon();
        }
        //返回 instance指向的對象
        return instance;
    }
      
}
  • TestGiantDragon.java
package charactor;
 
public class TestGiantDragon {
 
    public static void main(String[] args) {
        //通過new實例化會報錯
//      GiantDragon g = new GiantDragon();
         
        //只能通過getInstance得到對象
         
        GiantDragon g1 = GiantDragon.getInstance();
        GiantDragon g2 = GiantDragon.getInstance();
        GiantDragon g3 = GiantDragon.getInstance();
         
        //都是同一個對象
        System.out.println(g1==g2);
        System.out.println(g1==g3);
    }
}

4、什麼時候使用餓漢式?什麼時候使用懶漢式?

  • 餓漢式是立即加載的方式,無論是否會用到這個對象,都會加載。
    如果在構造方法裏寫了性能消耗較大,佔時較久的代碼,比如建立與數據庫的連接,那麼就會在啓動的時候感覺稍微有些卡頓。

  • 懶漢式,是延遲加載的方式,只有使用的時候纔會加載。 並且有線程安全的考量(鑑於同學們學習的進度,暫時不對線程的章節做展開)。
    使用懶漢式,在啓動的時候,會感覺到比餓漢式略快,因爲並沒有做對象的實例化。 但是在第一次調用的時候,會進行實例化操作,感覺上就略慢。

看業務需求,如果業務上允許有比較充分的啓動和初始化時間,就使用餓漢式,否則就使用懶漢式

5、單例模式三元素

這個是面試的時候經常會考的點,面試題通常的問法是:

什麼是單例模式?

回答的時候,要答到三元素

  1. 構造方法私有化
  2. 靜態屬性指向實例
  3. public static的 getInstance方法,返回第二步的靜態屬性

6、練習:單例模式

使用餓漢式單例模式, 把Hero類改造成爲單例模式

使用懶漢式單例模式,把Item類改造成爲單例模式

package charactor;
 
/**
 * 使用餓漢式單例模式, 把Hero類改造成爲單例模式
 */
public class Hero {
    private Hero() {
    }
 
    private static Hero hero = new Hero();
 
    private static Hero getInstance() {
        return hero;
    }
}
-------------------------------------------------------------
package charactor;
 
/**
 * 使用懶漢式單例模式,把Item類改造成爲單例模式
 */
public class Item {
    private Item() {
    }
 
    private static Item item;
 
    private static Item getInstance() {
        return item == null ? new Item() : item;
    }
}

7、參考鏈接

[01] How2j - 類和對象系列教材 (十二)- 怎麼寫一個JAVA的餓漢式與懶漢式單例模式

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