單例模式(Singleton)

/**

* 作者:wanglei 

* 郵箱:229846388@qq.com

* 單例模式

* Singleton.單例模式的一般實現(xiàn)

* 分類說明:

* 1.餓漢式:類加載時 自動初始化 單例

* 2.懶漢式:有需要的時候才手動調(diào)用 getInstance()初始化單例

* 區(qū)別:

* 1.懶漢式與餓漢式最大的區(qū)別是單例的初始化操作的時機(jī):

* 多線程下的單例模式實現(xiàn):

* 1.對于 餓漢式:多線程下適用,因為JVM只會加載一次單例類;

* 2.對于 懶漢式:多線程不適用,因為在創(chuàng)建單例時是線程不安全的。

* 3.即,多個線程可能會并發(fā)調(diào)用 newInstance (),從而重復(fù)創(chuàng)建單例對象

*/

/**

* 餓漢式

* 應(yīng)用場景:

* 1.應(yīng)用啟動時,需自動加載 & 初始化單例

* 2.單例對象要求初始化速度非常快且占用內(nèi)存非常小

*/

classHungryManSingleton{

/**

* 創(chuàng)建私有變量 instance(用以記錄 Singleton 的唯一實例)

* 內(nèi)部進(jìn)行實例化

*/

private staticHungryManSingletoninstance=newHungryManSingleton();

/**

* 把類的構(gòu)造方法私有化,不讓外部調(diào)用構(gòu)造方法實例化

*/

privateHungryManSingleton(){

}

/**

* 定義公有方法提供該類的全局唯一訪問點

*@return外部通過調(diào)用getInstance()方法來返回唯一的實例

*/

public staticHungryManSingletongetInstance(){

returninstance;

}

}

/**

* 懶漢式

* 應(yīng)用場景:

* 1.單例初始化的操作耗時長 & 應(yīng)用要求啟動速度快

* 2.單例的占用內(nèi)存比較大

* 3.單例只是在某個特定場景的情況下才會被使用,即按需延遲加載單例

*/

classLazyManSingleton{

/**

* 先賦值為Null,需要時才手動調(diào)用 getInstance() 創(chuàng)建

*/

private staticLazyManSingletoninstance=null;

privateLazyManSingleton(){

}

/**

* 先判斷單例是否為空,以避免重復(fù)創(chuàng)建

*@return外部通過調(diào)用getInstance()方法來返回唯一的實例

*/

public staticLazyManSingletongetInstance(){

if(instance==null){

instance=newLazyManSingleton();

}

returninstance;

}

}

/**

* 多線程下的單例模式實現(xiàn):

* 懶漢式

* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行

* 解決方案1:

* 1.同步鎖

* 2.使用同步鎖 synchronized (Singleton.class) ,防止多線程同時進(jìn)入,從而造成instance被多次實例化

* 缺點:

* 1.該解決方案的缺點在于:加鎖 = 非常耗時操作,耗時耗能

*/

classMultithreadingLazyManSingleton1{

private staticMultithreadingLazyManSingleton1instance=null;

privateMultithreadingLazyManSingleton1(){}

public staticMultithreadingLazyManSingleton1getInstance(){

/**

* 加入同步鎖

*/

synchronized(MultithreadingLazyManSingleton1.class){

if(instance==null){

instance=newMultithreadingLazyManSingleton1();

}

}

returninstance;

}

}

/**

* 多線程下的單例模式實現(xiàn):

* 懶漢式

* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行

* 解決方案2:

* 1.雙重校驗鎖

* 2.在同步鎖的基礎(chǔ)上,添加1層 if判斷:若Instance已實例化,則不必執(zhí)行加鎖操作就可以獲取實例,從而提高性能

* 缺點:

* 1.實現(xiàn)復(fù)雜 = 多種判斷,易出錯

*/

classMultithreadingLazyManSingleton2{

private staticMultithreadingLazyManSingleton2intance=null;

privateMultithreadingLazyManSingleton2(){}

public staticMultithreadingLazyManSingleton2getIntance(){

/**

* 在同步鎖的基礎(chǔ)上,添加1層if判斷 若單例已創(chuàng)建,則直接跳到執(zhí)行 return ourInstance

*/

if(intance==null){

synchronized(MultithreadingLazyManSingleton2.class){

if(intance==null){

intance=newMultithreadingLazyManSingleton2();

}

}

}

returnintance;

}

}

/**

* 多線程下的單例模式實現(xiàn):

* 懶漢式

* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行

* 解決方案3:

* 1.靜態(tài)內(nèi)部類

* 2.在內(nèi)部類里面去創(chuàng)建對象實例

*/

classMultithreadingLazyManSingleton3{

/**

* 在內(nèi)部類里面去創(chuàng)建對象實例對象;在裝載該內(nèi)部類時才會去創(chuàng)建單例

* 線程安全:類是由JVM加載的,而JVM只會加載一遍,保證只有1個單例模式,保證了數(shù)據(jù)同步

*/

private static classSingleton{

private staticSingletoninstance=newSingleton();

/**

* 私有構(gòu)造函數(shù)

*/

privateSingleton(){}

/**

*@return延遲加載、按需創(chuàng)建:外部調(diào)用類getInstance() ->調(diào)用Singleton.instance -> 創(chuàng)建實例

*/

public staticSingletongetInstance(){

returnSingleton.instance;

}

}

}

/**

* 多線程下的單例模式實現(xiàn):

* 懶漢式

* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行

* 解決方案4:

* 1.枚舉類型

* 2.最簡潔、易用的單例實現(xiàn)方式,(《Effective Java》推薦)

* 使用方式:

* MultithreadingLazyManSingleton4 singleton = MultithreadingLazyManSingleton4.instance;

* singleton.doSomething();

*/

enumMultithreadingLazyManSingleton4{

/**

*  定義一個枚舉的元素,它就是MultithreadingLazyManSingleton4的一個實例instance;

*/

instance;

public voiddoSomething(){

}

}

舉例說明:


/**

* 作者:wanglei 

* 郵箱:229846388@qq.com

* 單例模式

* 單例倉庫類

*/

public classStoreHouse {

/**

* 倉庫商品數(shù)量

*/

private intquantity=100;

/**

* //自己在內(nèi)部實例化

*/

private staticStoreHouseinstance=newStoreHouse();

/**

* 封閉構(gòu)造函數(shù)

*/

privateStoreHouse(){

}

/**

*@return讓外部通過調(diào)用getInstance()方法來返回唯一的實例。

*/

public staticStoreHousegetInstance(){

returninstance;

}

public intgetQuantity() {

returnquantity;

}

public voidsetQuantity(intquantity) {

this.quantity= quantity;

}

}


/**

* 作者:wanglei 

* 郵箱:229846388@qq.com

* 單例模式

* 搬貨工人類

*/

public classCarrier {

publicStoreHousemStoreHouse;

publicCarrier(StoreHouse storeHouse){

mStoreHouse= storeHouse;

}

/**

* 搬貨進(jìn)倉庫

*@parami

*/

public voidmoveIn(inti){

mStoreHouse.setQuantity(mStoreHouse.getQuantity() + i);

}

/**

* 搬貨出倉庫

*@parami

*/

public voidMoveOut(inti){

mStoreHouse.setQuantity(mStoreHouse.getQuantity() - i);

}

}


/**

* 作者:wanglei 

* 郵箱:229846388@qq.com

* 單例模式

* 解決的問題:

* 1.降低對象之間的耦合度

* 解決方法:

* 1.實現(xiàn)一個類只有一個實例化對象,并提供一個全局訪問點

*/

public classSimpleSinglePattern {

public static voidmain(String[] args){

StoreHouse storeHouse1 = StoreHouse.getInstance();

StoreHouse storeHouse2 = StoreHouse.getInstance();

Carrier carrier1 =newCarrier(storeHouse1);

Carrier carrier2 =newCarrier(storeHouse2);

System.out.println("兩個是不是同一個?");

if(storeHouse1.equals(storeHouse2)){

System.out.println("YES");

}else{

System.out.println("NO");

}

//搬運工搬完貨物之后出來匯報倉庫商品數(shù)量

carrier1.moveIn(30);

System.out.println("倉庫商品余量:"+ carrier1.mStoreHouse.getQuantity());

carrier2.MoveOut(50);

System.out.println("倉庫商品余量:"+ carrier2.mStoreHouse.getQuantity());

}

}

/**

* 結(jié)果:

* 兩個是不是同一個?

* YES

* 倉庫商品余量:130

* 倉庫商品余量:80

* 優(yōu)點:

* 1.提供了對唯一實例的受控訪問;

* 2.由于在系統(tǒng)內(nèi)存中只存在一個對象,因此可以節(jié)約系統(tǒng)資源,對于一些需要頻繁創(chuàng)建和銷毀的對象單例模式無疑可以提高系統(tǒng)的性能;

* 3.可以根據(jù)實際情況需要,在單例模式的基礎(chǔ)上擴(kuò)展做出雙例模式,多例模式;

* 缺點:

* 1.單例類的職責(zé)過重,里面的代碼可能會過于復(fù)雜,在一定程度上違背了“單一職責(zé)原則”。

* 2.如果實例化的對象長時間不被利用,會被系統(tǒng)認(rèn)為是垃圾而被回收,這將導(dǎo)致對象狀態(tài)的丟失。

*/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內(nèi)容