您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“Java設計模式的單例模式實例分析”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Java設計模式的單例模式實例分析”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
單例模式(Singleton Pattern)是 Java 中最簡單的設計模式之一。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。 這種模式涉及到一個單一的類,該類負責創建自己的對象,同時確保只有單個對象被創建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。
注意:
1、單例類只能有一個實例。
2、單例類必須自己創建自己的唯一實例。
3、單例類必須給所有其他對象提供這一實例。
單例模式大致分為懶漢式和餓漢式,接下來用案例分析
是否 Lazy 初始化: 是
是否多線程安全:否
實現難度: 易
描述: 這種方式是最基本的實現方式,這種實現最大的問題就是不支持多線程。因為沒有加鎖 synchronized,所以嚴格意義上它并不算單例模式。
這種方式 lazy loading 很明顯,不要求線程安全,在多線程不能正常工作。
概念看不懂沒關系,接下來舉例。
案例一:
創建一個劍類,這個類可以實例化一把劍。
虹貓和藍兔兩個人都想要造一把劍,虹貓先打造了一把劍,命名為長虹劍,然后藍兔也打造了一把劍,但是沒有命名。
現在來分析兩個情況,一個情況是正常模式,另一種情況是單例模式。
劍類:
public class Jians { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
測試類:
public class Demo1 { public static void main(String[] args) { //虹貓的劍 Jians hong = new Jians(); //藍兔的劍 Jians lan = new Jians(); hong.setName("長虹劍"); System.out.println(hong.getName()); System.out.println(lan.getName()); } }
結果:
在正常模式下,我new了虹貓和藍兔的劍。其實就是兩把劍,兩個不同的對象。
劍類:
劍類中的getInstance()方法有一個造劍的功能,也就是new一個劍對象的功能。
public class Jian { private static Jian jian; private String name; public static Jian getInstance() { if (jian == null) { jian = new Jian(); } return jian; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
測試類:
public class Demo { public static void main(String[] args) { //虹貓的劍 Jian hong = Jian.getInstance(); //藍兔的劍 Jian lan = Jian.getInstance(); //虹貓把劍命名長虹劍 hong.setName("長虹劍"); //輸出 System.out.println(hong.getName()); System.out.println(lan.getName()); } }
結果:
在單例模式下,我new了虹貓和藍兔的劍。其實就是一把劍,一個相同的對象。
單例模式下的劍類:
public class Jian { private static Jian jian; private String name; public static Jian getInstance() { if (jian == null) { jian = new Jian(); } return jian; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
就拿這個類來說,他是線程不安全的。因為他通過getInstance()方法來獲取對象。如果是多線程運行,有線程1和線程2都先后進入了這個方法,因為線程1剛進入方法還沒有返回對象,線程2就進入了方法。所以線程2也會new一個對象,因為此時線程2進入方法的時候jian還是null的。
是否 Lazy 初始化: 是
是否多線程安全: 是
實現難度: 易
描述: 這種方式具備很好的 lazy loading,能夠在多線程中很好的工作,但是,效率很低,99% 情況下不需要同步。
優點: 第一次調用才初始化,避免內存浪費。
缺點: 必須加鎖 synchronized 才能保證單例,但加鎖會影響效率。
這里還用上面那個案例,這次主要介紹懶漢式一和懶漢式二的區別。
懶漢式一和懶漢式二的主要區別在劍類上。
懶漢式一的劍類:
public class Jian { private static Jian jian; private String name; public static Jian getInstance() { if (jian == null) { jian = new Jian(); } return jian; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
懶漢式二的劍類:
public class Jian { private static Jian jian; private String name; public static synchronized Jian getInstance() { if (jian == null) { jian = new Jian(); } return jian; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在getInstance()方法前加了個字段synchronized,synchronized是一把鎖,作用是同一時間只能有一個線程進入這個方法,這樣就避免了懶漢式一中兩個線程都進入方法的情況出現,就不會new兩個對象,所以線程安全。
是否 Lazy 初始化: 否
是否多線程安全: 是
實現難度: 易
描述: 這種方式比較常用,但容易產生垃圾對象。
優點: 沒有加鎖,執行效率會提高。
缺點: 類加載時就初始化,浪費內存。
餓漢式就是直接在類中new一個對象,就是不管你需不需要劍我已經把劍造好了。
餓漢式劍類:
public class Jian { private static Jian jian=new Jian(); private String name; public static synchronized Jian getInstance() { return jian; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
測試類:
public class Demo { public static void main(String[] args) { //虹貓的劍 Jian hong = Jian.getInstance(); //藍兔的劍 Jian lan = Jian.getInstance(); //虹貓把劍命名長虹劍 hong.setName("長虹劍"); //輸出 System.out.println(hong.getName()); System.out.println(lan.getName()); } }
餓漢式中劍類的getInstance()方法已經失去了造劍的功能,測試類調用它只是返回一把提前造好的劍
還是這個案例,虹貓和藍兔都想造一把劍,懶漢式是有一個劍類,劍類中有一個造劍的方法,調用這個方法的時候打造一把劍。餓漢式也有一個劍類,不同的是這個劍類直接就把劍造好了,沒有造劍的方法,不管你虹貓和藍兔想不想造劍,劍都已經造好了。
優點: 沒有加鎖,執行效率會提高。 缺點: 類加載時就初始化,浪費內存。
現在在看餓漢式的優缺點就容易理解了。
讀到這里,這篇“Java設計模式的單例模式實例分析”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。