自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

小小的單例模式竟然有這么多種寫(xiě)法?

開(kāi)發(fā) 前端
單例模式應(yīng)該是設(shè)計(jì)模式中最容易理解也是用得最多的一種模式了,同時(shí)也是面試的時(shí)候最常被問(wèn)到的模式。

[[404953]]

單例模式應(yīng)該是設(shè)計(jì)模式中最容易理解也是用得最多的一種模式了,同時(shí)也是面試的時(shí)候最常被問(wèn)到的模式。

1. 單例模式的定義

單例模式指的是一個(gè)類中在任何情況下都絕對(duì)只有一個(gè)實(shí)例,并且提供一個(gè)全局訪問(wèn)點(diǎn)。

2. 單例模式的應(yīng)用場(chǎng)景

單例模式的應(yīng)用非常廣泛,如數(shù)據(jù)庫(kù)中的連接池、J2EE中的ServletContext和ServletContextConfig、Spring框架中的ApplicationContext等等。然而在Java中,單例模式還可以保證一個(gè)JVM中只存在一個(gè)唯一的實(shí)例。

單例模式的應(yīng)用場(chǎng)景主要有以下幾個(gè)方面:

  • 當(dāng)需要頻繁創(chuàng)建一些類的時(shí)候,使用單例可以降低系統(tǒng)的內(nèi)存壓力,減少GC(垃圾回收) ;
  • 當(dāng)某些類創(chuàng)建實(shí)例時(shí)候需要占用的資源較多,或者實(shí)例化過(guò)程耗時(shí)比較長(zhǎng),且經(jīng)常使用的情況;
  • 當(dāng)存在頻繁訪問(wèn)數(shù)據(jù)庫(kù)或者文件的對(duì)象;
  • 當(dāng)對(duì)于一些控制硬件級(jí)別的操作,或者從系統(tǒng)上來(lái)講應(yīng)當(dāng)是單一控制邏輯的操作,是不允許存在多個(gè)實(shí)例的,否則玩完;

3. 單例模式的優(yōu)缺點(diǎn)

3.1 單例模式的優(yōu)點(diǎn)

  • 單例模式可以保證內(nèi)存中只有一個(gè)實(shí)例對(duì)象,從而會(huì)減少內(nèi)存的開(kāi)銷(xiāo);
  • 單例模式可以避免對(duì)資源的多重占用;
  • 單例模式設(shè)置全局訪問(wèn)點(diǎn),可以起到優(yōu)化和共享資源的訪問(wèn)的作用;

3.2 單例模式的缺點(diǎn)

  • 擴(kuò)展難, 因?yàn)閱卫J酵ǔJ菦](méi)有接口的啊,如果想要擴(kuò)展,那么你唯一途徑就是修改之前的代碼,所以說(shuō)單例模式違背了開(kāi)閉原則;
  • 調(diào)試難,因?yàn)樵诓l(fā)測(cè)試中,單例模式是不利于代碼的調(diào)試的,單例中的代碼沒(méi)有執(zhí)行完,也不能模擬生成一個(gè)新對(duì)象;
  • 違背單一職責(zé)原則,因?yàn)閱卫J降臉I(yè)務(wù)代碼通常寫(xiě)在一個(gè)類中,如果功能設(shè)計(jì)不合理,就很容易違背單一職責(zé)原則;

4. 單例模式的實(shí)現(xiàn)方式及其優(yōu)缺點(diǎn)

4.1 單例模式的餓漢式實(shí)現(xiàn)

4.1.1 餓漢式標(biāo)準(zhǔn)寫(xiě)法

Singleton類稱為單例類,通過(guò)內(nèi)部初始化一次 , 隱藏構(gòu)造方法, 并提供一個(gè)全局訪問(wèn)點(diǎn)的方式實(shí)現(xiàn)。

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式的通用寫(xiě)法 
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class Singleton { 
  8.     /** 
  9.      * 內(nèi)部初始化一次 
  10.      */ 
  11.     private static final Singleton instance = new Singleton(); 
  12.  
  13.     /** 
  14.      * 隱藏構(gòu)造方法 
  15.      */ 
  16.     private Singleton() { 
  17.     } 
  18.  
  19.     /** 
  20.      * 提供一個(gè)全局訪問(wèn)點(diǎn) 
  21.      * 
  22.      * @return Singleton 
  23.      */ 
  24.     public static Singleton getInstance() { 
  25.         return instance; 
  26.     } 
  27.  

以上餓漢式單例寫(xiě)法在類的初始化的時(shí)候就會(huì)進(jìn)行初始化操作,并且創(chuàng)建對(duì)象,絕對(duì)的線程安全,因?yàn)榇藭r(shí)線程還沒(méi)有出現(xiàn)就已經(jīng)實(shí)例化了,故不會(huì)存在訪問(wèn)安全的問(wèn)題。

4.1.2 餓漢式靜態(tài)塊機(jī)制寫(xiě)法

餓漢式還有一種實(shí)現(xiàn),那就是靜態(tài)塊機(jī)制,如下代碼所示:

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式  餓漢式靜態(tài)機(jī)制 實(shí)現(xiàn) 
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class HungryStaticSingleton { 
  8.      
  9.     private static final HungryStaticSingleton hungrySingleton; 
  10.     //靜態(tài)代碼塊 類加載的時(shí)候就初始化 
  11.     static { 
  12.         hungrySingleton=new HungryStaticSingleton(); 
  13.     } 
  14.     /** 
  15.      * 私有化構(gòu)造函數(shù) 
  16.      */ 
  17.     private HungryStaticSingleton(){} 
  18.  
  19.     /** 
  20.      * 提供一個(gè)全局訪問(wèn)點(diǎn) 
  21.      * @return 
  22.      */ 
  23.     public static HungryStaticSingleton getInstance() { 
  24.         return hungrySingleton; 
  25.     } 

我們分析一下這種是寫(xiě)法 ,可以明顯的看到所以對(duì)象是類在加載的時(shí)候就進(jìn)行實(shí)例化了,那么這樣一來(lái),會(huì)導(dǎo)致單例對(duì)象的數(shù)量不確定,從而會(huì)導(dǎo)致系統(tǒng)初始化的時(shí)候就造成大量?jī)?nèi)存浪費(fèi),況且你用不用還不一定,還一直占著空間,俗稱“占著茅坑不拉屎”。

4.2 單例模式的懶漢式實(shí)現(xiàn)

為了解決餓漢式單例寫(xiě)法可能帶來(lái)的內(nèi)存浪費(fèi)問(wèn)題,這里分析一下懶漢式單例的寫(xiě)法。如下代碼所示:

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式  懶漢式單例實(shí)現(xiàn) 
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class LazySimpleSingleton { 
  8.  
  9.     private static LazySimpleSingleton lazySingleton = null
  10.  
  11.     /** 
  12.      * 私有化構(gòu)造函數(shù) 
  13.      */ 
  14.     private LazySimpleSingleton() { 
  15.  
  16.     } 
  17.     /** 
  18.      * 提供一個(gè)全局訪問(wèn)點(diǎn) 
  19.      * 
  20.      * @return 
  21.      */ 
  22.     public static LazySimpleSingleton getInstance() { 
  23.         if (lazySingleton == null) { 
  24.             lazySingleton = new LazySimpleSingleton(); 
  25.         } 
  26.         return lazySingleton; 
  27.     } 

這樣實(shí)現(xiàn)的好處就是只有對(duì)象被使用的時(shí)候才會(huì)進(jìn)行初始化,不會(huì)存在內(nèi)存浪費(fèi)的問(wèn)題,但是它會(huì)在多線程環(huán)境下,存在線程安全問(wèn)題。我們可以利用synchronized關(guān)鍵字將全局訪問(wèn)點(diǎn)方法變成一個(gè)同步方法,這樣就可以解決線程安全的問(wèn)題,代碼如下所示:

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式  懶漢式單例實(shí)現(xiàn) synchronized修飾  
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class LazySimpleSingleton { 
  8.     private static LazySimpleSingleton lazySingleton = null
  9.     /** 
  10.      * 私有化構(gòu)造函數(shù) 
  11.      */ 
  12.     private LazySimpleSingleton() {} 
  13.     /** 
  14.      * 提供一個(gè)全局訪問(wèn)點(diǎn)   
  15.      * 
  16.      * @return 
  17.      */ 
  18.     public synchronized static  LazySimpleSingleton getInstance() { 
  19.         if (lazySingleton == null) { 
  20.             lazySingleton = new LazySimpleSingleton(); 
  21.         } 
  22.         return lazySingleton; 
  23.     } 

但是,這樣雖然解決了線程安全的問(wèn)題,可是如果在線程數(shù)量劇增的情況下,用synchronized加鎖,則會(huì)導(dǎo)致大批線程阻塞,從而驟減系統(tǒng)性能。

4.3 單例模式的雙重檢測(cè)實(shí)現(xiàn)

在上述代碼上進(jìn)一步優(yōu)化,代碼如下所示:

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式  懶漢式-雙重檢測(cè)單例實(shí)現(xiàn) 
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class LazyDoubleCheckSingleton { 
  8.     // volatile 關(guān)鍵字修飾 
  9.     private volatile static LazyDoubleCheckSingleton lazySingleton ; 
  10.     /** 
  11.      * 私有化構(gòu)造函數(shù) 
  12.      */ 
  13.     private LazyDoubleCheckSingleton() {} 
  14.     /** 
  15.      * 提供一個(gè)全局訪問(wèn)點(diǎn) 
  16.      * 
  17.      * @return 
  18.      */ 
  19.     public static LazyDoubleCheckSingleton getInstance() { 
  20.         // 這里先判斷一下是否阻塞 
  21.         if (lazySingleton == null) { 
  22.             synchronized (LazyDoubleCheckSingleton.class){ 
  23.                 // 判斷是否需要重新創(chuàng)建實(shí)例 
  24.                 if (lazySingleton == null) { 
  25.                     lazySingleton = new LazyDoubleCheckSingleton(); 
  26.                 } 
  27.             } 
  28.         } 
  29.         return lazySingleton; 
  30.     } 

()方法時(shí),第二個(gè)線程也可以調(diào)用,但是第一個(gè)線程執(zhí)行synchronized時(shí)候,第二個(gè)線程就會(huì)發(fā)現(xiàn)阻塞,但是此時(shí)的阻塞是getInstance()內(nèi)部的阻塞。

4.4 單例模式的靜態(tài)內(nèi)部類實(shí)現(xiàn)

雖然雙重檢測(cè)鎖的單例模式解決了線程安全和性能問(wèn)題,但是畢竟涉及加鎖的操作,多多少少就會(huì)到了性能的影響,下面我們分享一下更加優(yōu)雅的單例模式實(shí)現(xiàn),如下代碼所示:

  1. /** 
  2.  * msJava 
  3.  * 
  4.  * @Description 單例模式  靜態(tài)內(nèi)部類單例實(shí)現(xiàn) 
  5.  * @Date 2021-01-23 
  6.  */ 
  7. public class LazyStaticInnerClassSingleton { 
  8.     //  在構(gòu)造方法里面拋出異常真的合適? 
  9.   private LazyStaticInnerClassSingleton(){ 
  10.     if(LazyHolder.INSTANCE != null){ 
  11.         throw new RuntimeException("不允許創(chuàng)建多個(gè)實(shí)例"); 
  12.     } 
  13.   } 
  14.   // static 保證這個(gè)方法不會(huì)被重寫(xiě) 覆蓋 
  15.   private static LazyStaticInnerClassSingleton getInstance(){ 
  16.       return LazyHolder.INSTANCE; 
  17.   } 
  18.   // Java 默認(rèn)不會(huì)加載內(nèi)部類 
  19.   private static class LazyHolder{ 
  20.       private static final LazyStaticInnerClassSingleton INSTANCE=new LazyStaticInnerClassSingleton(); 
  21.   } 

5. 總結(jié)

 

單例模式面試幾乎必備!

 

責(zé)任編輯:武曉燕 來(lái)源: 碼上Java
相關(guān)推薦

2021-02-03 20:19:08

Istio流量網(wǎng)格

2020-11-02 08:35:59

內(nèi)存數(shù)據(jù)庫(kù)Redis

2016-09-01 13:54:23

Google太空電梯懸滑板

2013-01-24 09:44:44

數(shù)據(jù)庫(kù)

2024-05-13 16:22:25

固態(tài)硬盤(pán)接口硬盤(pán)

2020-06-01 08:04:18

三目運(yùn)算符代碼

2015-05-18 15:08:08

多種程序設(shè)計(jì)語(yǔ)言程序設(shè)計(jì)語(yǔ)言

2022-03-03 07:00:43

Mybatiswhere標(biāo)簽

2024-04-02 08:41:10

ArrayListSubList場(chǎng)景

2022-08-10 11:02:56

Python單例模式

2022-05-23 07:35:15

單例模式懶漢模式靜態(tài)內(nèi)部類

2018-06-26 15:00:24

Docker安全風(fēng)險(xiǎn)

2017-06-16 16:16:36

庫(kù)存扣減查詢

2017-03-07 17:45:42

Windows磁盤(pán)碎片整理

2019-12-09 10:13:20

HashMap選擇容量

2010-02-03 09:43:16

C++單例模式

2013-01-15 09:41:45

編程語(yǔ)言

2023-07-26 00:32:33

注解抽象spring

2024-02-20 08:09:51

Java 8DateUtilsDate工具類

2023-11-13 08:49:54

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)