单例模式【SingletonPattern】
這個模式是很有意思,而且比較簡單,但是我還是要說因為它使用的是如此的廣泛,如此的有人緣,單例就是單一、獨苗的意思,那什么是獨一份呢?你的思維是獨一份,除此之外還有什么不能山寨的呢?我們舉個比較難復(fù)制的對象:皇帝
中國的歷史上很少出現(xiàn)兩個皇帝并存的時期,是有,但不多,那我們就認(rèn)為皇帝是個單例模式,在這個場景中,有皇帝,有大臣,大臣是天天要上朝參見皇帝的,今天參拜的皇帝應(yīng)該和昨天、前天的一樣(過渡期的不考慮,別找茬哦),大臣磕完頭,抬頭一看,嗨,還是昨天那個皇帝,單例模式,絕對的單例模式,先看類圖:
然后我們看程序?qū)崿F(xiàn),先定一個皇帝:package com.cbf4life.singleton1;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 中國的歷史上一般都是一個朝代一個皇帝,有兩個皇帝的話,必然要PK出一個皇帝出來*/
public class Emperor {
private static Emperor emperor = null; //定義一個皇帝放在那里,然后給這個皇帝名字
private Emperor(){//世俗和道德約束你,目的就是不讓你產(chǎn)生第二個皇帝
}
public static Emperor getInstance(){
第 12 頁
if(emperor == null){ //如果皇帝還沒有定義,那就定一個emperor = new Emperor();
}
return emperor;}
//皇帝叫什么名字呀
public static void emperorInfo(){
System.out.println("我就是皇帝某某某....");}
}
然后定義大臣:
package com.cbf4life.singleton1;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.
* 大臣是天天要面見皇帝,今天見的皇帝和昨天的,前天不一樣那就出問題了!*/
@SuppressWarnings("all")public class Minister {
/**
* @param args*/
public static void main(String[] args) {//第一天
Emperor emperor1=Emperor.getInstance();emperor1.emperorInfo(); //第一天見的皇帝叫什么名字呢?
//第二天
Emperor emperor2=Emperor.getInstance();Emperor.emperorInfo();
//第三天
Emperor emperor3=Emperor.getInstance();emperor2.emperorInfo();
//三天見的皇帝都是同一個人,榮幸吧!}
}
您的設(shè)計模式
第 13 頁
您的設(shè)計模式
看到?jīng)],大臣天天見到的都是同一個皇帝,不會產(chǎn)生錯亂情況,反正都是一個皇帝,是好是壞就這一個,只要提到皇帝,大家都知道指的是誰,清晰,而又明確。問題是這是通常情況,還有個例的,如同一個時期同一個朝代有兩個皇帝,怎么辦?
單例模式很簡單,就是在構(gòu)造函數(shù)中多了加一個構(gòu)造函數(shù),訪問權(quán)限是 private 的就可以了,這個模式是簡單,但是簡單中透著風(fēng)險,風(fēng)險?什么風(fēng)險?在一個 B/S 項目中,每個 HTTP Request 請求到 J2EE的容器上后都創(chuàng)建了一個線程,每個線程都要創(chuàng)建同一個單例對象,怎么辦?,好,我們寫一個通用的單例程序,然后分析一下:
package com.cbf4life.singleton3;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.* 通用單例模式
*/
@SuppressWarnings("all")public class SingletonPattern {
private static SingletonPattern singletonPattern= null;//限制住不能直接產(chǎn)生一個實例
private SingletonPattern(){
}
public SingletonPattern getInstance(){
return this.singletonPattern;}
}
我們來看黃色的那一部分,假如現(xiàn)在有兩個線程 A 和線程 B,線程 A 執(zhí)行到 this.singletonPattern =new SingletonPattern(),正在申請內(nèi)存分配,可能需要 0.001 微秒,就在這 0.001 微秒之內(nèi),線程 B 執(zhí)行到 if(this.singletonPattern == null),你說這個時候這個判斷條件是 true 還是 false?是 true,那然后呢?線程 B 也往下走,于是乎就在內(nèi)存中就有兩個 SingletonPattern 的實例了,看看是不是出問題了?
if(this.singletonPattern == null){ //如果還沒有實例,則創(chuàng)建一個
this.singletonPattern = new SingletonPattern();
}
第 14 頁
您的設(shè)計模式
如果你這個單例是去拿一個序列號或者創(chuàng)建一個信號資源的時候,會怎么樣?業(yè)務(wù)邏輯混亂!數(shù)據(jù)一致性校驗失敗!最重要的是你從代碼上還看不出什么問題,這才是最要命的!因為這種情況基本上你是重現(xiàn)不了的,不寒而栗吧,那怎么修改?有很多種方案,我就說一種,能簡單的、徹底解決問題的方案:
package com.cbf4life.singleton3;
/**
* @author cbf4Life cbf4life@126.com
* I'm glad to share my knowledge with you all.* 通用單例模式
*/
@SuppressWarnings("all")public class SingletonPattern {
//限制住不能直接產(chǎn)生一個實例private SingletonPattern(){}
public synchronized static SingletonPattern getInstance(){return singletonPattern;
}}
直接 new 一個對象傳遞給類的成員變量 singletonpattern,你要的時候 getInstance()直接返回給你,解決問題!
總結(jié)
以上是生活随笔為你收集整理的单例模式【SingletonPattern】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 音响插主机后面哪个孔
- 下一篇: Spring Data Jpa 投影(P