單例模式是啥????故名思意,就是單著的意思 = =!沒錯,就是為了來保證整個系統執行中,從頭至尾只有乙個物件。比如說,我們最可愛的學校,可以有很多學生,可以有很多主任,但是不能有很多校長。為什麼?因為要確保只有乙個校長,學校這個系統才不會因為受干擾崩潰,所以單例模式應運而生。
都知道了單例模式是幹嘛的了,那就好辦了。首先你要確保整個系統的laowang類只有老王乙個物件最重要的前提你要做什麼??可想而知,老王不能被其他類所創造出來啊。
因此有如下做法:
1. 先把構造方法給私有化了(private)。
2. 接著在程式執行的時候建立乙個物件放在記憶體裡就得了。
你沒看錯,要實現單例模式,確確實實就只有這兩步,第一步2秒鐘搞定,第二步就是我們要來**的部分了。
實現單例模式有五種做法:
1. 餓漢式
分為兩步走:
把構造方法私有化
在程式裝載時提前建立好例項
class laowang//私有化構造方法
private static laowang laowang=new laowang();//直接建立靜態例項
//對外提供靜態方法獲取當前的laowang
public static laowang getlaowang()
}//main方法
public static void main(string args)
執行結果: true
上面這個例子中,在老王這個類中,先私有化構造方法,接著建立乙個靜態屬性laowang, 然後提供乙個對外的靜態方法getlaowang()可以給別人拿這個laowang。(因為你已經把構造方法私有化了,所以你只能通過靜態方法把laowang給別人。)
main方法中定義了2個引用laowang1,laowang2,但是都是通過同一種方式拿到例項物件laowang.因此拿到的是同乙個物件,所以返回true,這就是餓漢式實現法。
優點:實現簡單,執行緒安全。
缺點:很明顯,在類裝載的時候直接建立,有時候你不需要它,它也會創 建,造成記憶體資源浪費。
餓漢式也有另外一種寫法,也是一樣的效果。把new laowang()放在靜態**塊裡,如下:
class laowang//私有化構造方法
static
//對外提供靜態方法獲取當前的laowang
public static laowang getlaowang()
}
2. 懶漢式
在程式需要用到呼叫的時候才給它(懶載入),因此做法如下:
class laowang//私有化構造方法
//對外提供靜態方法,建立例項然後返回,當前的laowang
public static synchronized laowang getlaowang()
return laowang;
}}
此做法需要在方法宣告加上synchronized,(具體作用:比如說很多人來訪問這個方法,他們必須排隊訪問) 這種怎麼理解呢?就是說在別人需要用到laowang,呼叫getlaowang()的時候,先排隊,排到他的時候,進去判斷laowang是不是為空,是就new乙個,不是就拿當前laowang給他。當然main執行結果還是為true這裡就不作多的描述。
優點:不會造成記憶體浪費
缺點:很明顯,人人平等,大家都要排隊,既然排隊就慢,高併發情況下,極度影響效率。
在這裡解釋為什麼要加同步鎖:如果不加的話,舉個例子,程式執行剛開始,小黑和小紅同時訪問這個方法,同時作判斷,肯定同時都判斷為空,而且兩個人都進去了,new laowang();很明顯直接造成laowang不是單例的了。因此要加鎖。 小黑小紅都要排隊。
3. 雙重檢驗鎖
也是屬於懶載入
class laowang//私有化構造方法
//對外提供靜態方法,建立例項然後返回,當前的laowang
public static laowang getlaowang()}}
return laowang;
}}
舉個例子解釋一下為什麼要這樣做:
還是小黑小紅,同時併發進來訪問,然後肯定同時第一次判斷都為空,接著兩個人排隊,小黑先進去玩會,肯定第二次判斷為空,結果肯定是小黑new了乙個laowang走了。排到小紅了,小紅進來第二次判斷發現laowang不為空了,直接帶走。
這個時候有人問了,那為什麼要第一次判斷幹嘛,直接排隊他不香嗎?沒錯,我第一次也這不理解的地方。我們腦迴路回退到小黑剛new完laowang走了。剛要排到小紅了。突然來了個第三者小三,如果你沒有第一次判斷,小三還要繼續排在小紅後面,造成效率降低。但是現在小三第一次判斷發現laowang已經不為空了(此時laowang是第乙個人小黑弄出來的),直接帶走。
優點:解決了排隊效率降低的問題,執行緒安全。
缺點:實現較為複雜。
4. 內部類方式
也是屬於懶載入,故名思意,首先整個內部類出來,**如下:
兄台要看如下**,請先了解final關鍵字的作用
這裡對final作簡單描述:
對類使用:表示該類不能被繼承(俗稱斷子絕孫類)
對方法使用:表示該方法不能被重寫
對基礎型別使用:比如說int,float…表示該值不可以被更改
對引用物件使用:表示該引用從頭到尾只指向乙個物件
以上3.對基礎型別使用,4.對引用物件使用都必須直接賦值。
class laowang //私有化構造方法
//對外提供靜態方法,呼叫內部類的屬性,返回
public static final laowang getlaowang()
//靜態內部類
private static final class laowangholder
}
解釋以上**:首先宣告了乙個內部類(laowangholder),他有個靜態且被final修飾的屬性instance,因此需要直接賦值,new laowang();接著在getlaowang()方法中呼叫內部類的instance屬性,返回。因為instance被final修飾,只指向同乙個laowang,所以他是單例的。
這些方法實現相對簡單,所以直接上**:
enum laowang
}//main方法:
public static void main(string args)
直接宣告乙個列舉類,定義乙個屬性,main方法中直接獲取即可。
單例模式執行緒安全的就這幾種了,反正我自己是搞懂了,希望你們也能看懂。想看對單例了解更深入可以點我下方的鏈結。看有經驗的人說,單例是最常用的也是最簡單的一種設計模式之一,在工作中實現方式大都選擇餓漢式,或者內部類,列舉,但是懶漢,雙重校驗鎖就比較少了。
學完之後自己想在之前專案中實現乙個單例的map,用來儲存登陸驗證時的token,就不用每次都往資料庫裡存了,算是做了一層快取,提高效能吧。
好了,本文到此為止,希望大家都能有所收穫。
此文知識點借鑑於菜鳥程式設計——單例模式
創作不易,兄弟姐妹們點讚收藏加關注,你們的鼓勵就是我最大的動力!
未完待續,**中…
SINGLETON 單例模式 孤獨的人
很多時候,我們都很彷徨,因為,在身邊的朋友,很少。package patterns.createable.singleton 孤獨的人啊 我為你寫了乙個類 這個類,在我們的程式中 只能唯一 author one public class singleton public static synchro...
單例模式 單例模式
餓漢式 急切例項化 public class eagersingleton 2.宣告靜態成員變數並賦初始值 類初始化的時候靜態變數就被載入,因此叫做餓漢式 public static eagersingleton eagersingleton new eagersingleton 3.對外暴露公共的...
單例 單例模式
簡單的實現乙個單例 instancetype sharedinstance return instance 真正的單例模式 myclass sharedinstance return instance id allocwithzone nszone zone return nil id copywi...