茴香豆的“茴”字有幾種寫法蹋半?
有一回對我說道,“你讀過書么染突?”我略略點一點頭辈灼。他說,“讀過書巡莹,……我便考你一考甜紫。茴香豆的茴字骂远,怎樣寫的?”我想激才,討飯一樣的人,也配考我么贸营?便回過臉去,不再理會揣云”校孔乙己等了許久,很懇切的說道焚刚,“不能寫罷扇调?……我教給你,記著狼钮!這些字應(yīng)該記著熬芜。將來做掌柜的時候,寫賬要用涎拉。”我暗想我和掌柜的等級還很遠呢半火,而且我們掌柜也從不將茴香豆上賬季俩;又好笑,又不耐煩藐鹤,懶懶的答他道,“誰要你教娱节,不是草頭底下一個來回的回字么肄满?”孔乙己顯出極高興的樣子,將兩個指頭的長指甲敲著柜臺稠歉,點頭說,“對呀對呀带饱!……茴字有四樣寫法阅羹,你知道么?(留言回復(fù)你知道的茴字四種寫法)
面試中會問到單例模式执庐,選擇其中一種或幾種寫法作為話頭导梆,考查設(shè)計模式和coding style的同時,還很容易擴展到其他問題递鹉。這里講解8種常用的寫法狡忙,下次遇到面試官可以直接甩到他面前址芯!但切忌生搬硬套,去記“茴香豆的寫法”北专。
簡介
單例模式是一種常用的軟件設(shè)計模式旬陡,其定義是單例對象的類只能允許一個實例存在。
實現(xiàn)思路
單例模式是一種常用的軟件設(shè)計模式驶睦,其定義是單例對象的類只能允許一個實例存在。單例模式要求類能夠有返回對象一個引用(永遠是同一個)和一個獲得該實例的方法(必須是靜態(tài)方法场航,通常使用getInstance這個名稱)溉痢。
8種寫法
1.餓漢式一
優(yōu)點:這種寫法比較簡單,靜態(tài)常量孩饼,就是在類裝載的時候就完成實例化。避免了線程同步問題立膛。
缺點:在類裝載的時候就完成實例化梯码,沒有達到Lazy Loading的效果。如果從始至終從未使用過這個實例鲁猩,則會造成內(nèi)存的浪費罢坝。
代碼:
public?class?Singleton {
//私有靜態(tài)常量
?? ?private?final?static?Singleton INSTANCE?=?new?Singleton();
//私有構(gòu)造
?? ?private?Singleton(){}
?//靜態(tài)工廠方法
?? ?public?static?Singleton getInstance(){
?? ??? ?return?INSTANCE;
?? ?}
}
2.餓漢式二
這種方式和上面的方式其實類似嘁酿,只不過將類實例化的過程放在了靜態(tài)代碼塊中,也是在類裝載的時候闹司,就執(zhí)行靜態(tài)代碼塊中的代碼,初始化類的實例牲迫。優(yōu)缺點和上面是一樣的借卧。
代碼:
public?class?Singleton {
?? ?private?static?Singleton instance;
?//靜態(tài)代碼塊
?? ?static?{
?? ??? ?instance?=?new?Singleton();
?? ?}
? ? ?//私有構(gòu)造
?? ?private?Singleton() {}
?? ?public?Singleton getInstance() {
?? ??? ?return?instance;
?? ?}
}
3.懶漢式一
這種寫法起到了Lazy Loading的效果铐刘,但是只能在單線程下使用。如果在多線程下,一個線程進入了if (singleton == null)判斷語句塊挂签,還未來得及往下執(zhí)行盼产,另一個線程也通過了這個判斷語句,這時便會產(chǎn)生多個實例啦辐。所以在多線程環(huán)境下不可使用這種方式蜈项。
代碼:
public?class?Singleton {
?? ?private?static?Singleton singleton;
//私有構(gòu)造
?? ?private?Singleton() {}
?? ?public?static?Singleton getInstance() {
?? ??? ?if?(singleton?==?null) {
?? ??? ??? ?singleton?=?new?Singleton();
?? ??? ?}
?? ??? ?return?singleton;
?? ?}
}
4.懶漢式二
解決上面第三種實現(xiàn)方式的線程不安全問題,做個線程同步就可以了侥衬,于是就對getInstance()方法進行了線程同步跑芳。缺點:效率太低了,每個線程在想獲得類的實例時候怀樟,執(zhí)行g(shù)etInstance()方法都要進行同步盆佣。而其實這個方法只執(zhí)行一次實例化代碼就夠了,后面的想獲得該類實例虑灰,直接return就行了痹兜。方法進行同步效率太低要改進。
代碼:
public?class?Singleton {
?? ?private?static?Singleton?singleton;
//私有構(gòu)造
?? ?private?Singleton() {}
?? ?public?static?synchronized?Singleton getInstance() {
?? ??? ?if?(singleton?==?null) {
?? ??? ??? ?singleton?=?new?Singleton();
?? ??? ?}
?? ??? ?return?singleton;
?? ?}
}
5.懶漢式三
由于第四種實現(xiàn)方式同步效率太低对湃,所以摒棄同步方法谐算,改為同步產(chǎn)生實例化的的代碼塊归露。但是這種同步并不能起到線程同步的作用。跟第3種實現(xiàn)方式遇到的情形一致恐锦,假如一個線程進入了if (singleton == null)判斷語句塊,還未來得及往下執(zhí)行陕贮,另一個線程也通過了這個判斷語句潘飘,這時便會產(chǎn)生多個實例。
代碼:
public?class?Singleton {
?? ?private?static?Singleton singleton;
//私有構(gòu)造
?? ?private?Singleton() {}
?? ?public?static?Singleton getInstance() {
?? ??? ?if?(singleton?==?null) {
?? ??? ??? ?synchronized?(Singleton.class) {
?? ??? ??? ?singleton?=?new?Singleton();
?? ??? ?}
?? ?}
?? ?return?singleton;
?? ?}
}
6.雙重檢查
Double-Check概念對于多線程開發(fā)者來說不會陌生戈擒,如代碼中所示艰毒,我們進行了兩次if (singleton == null)檢查丑瞧,這樣就可以保證線程安全了。這樣绊汹,實例化代碼只用執(zhí)行一次,后面再次訪問時诫欠,判斷if (singleton == null)浴栽,直接return實例化對象。優(yōu)點:線程安全被廓;延遲加載萝玷;效率較高。
代碼:
public?class?Singleton {
?? ?private?static?volatile?Singleton singleton;
//私有構(gòu)造
?? ?private?Singleton() {}
//?雙重檢查
?? ?public?static?Singleton getInstance() {
?? ??? ?if?(singleton?==?null) {
?? ??? ??? ?synchronized?(Singleton.class) {
//里面的判斷是一定要加的蜓斧,否則出現(xiàn)線程安全問題
?? ??? ??? ??? ?if?(singleton?==?null) {
?? ??? ??? ??? ??? ?singleton?=?new?Singleton();
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return?singleton;
?? ?}
}
7.靜態(tài)內(nèi)部類
這種方式跟餓漢式方式采用的機制類似睁冬,但又有不同。兩者都是采用了類裝載的機制來保證初始化實例時只有一個線程直奋。不同的地方在餓漢式方式是只要Singleton類被裝載就會實例化,沒有Lazy-Loading的作用搁胆,而靜態(tài)內(nèi)部類方式在Singleton類被裝載時并不會立即實例化邮绿,而是在需要實例化時,調(diào)用getInstance方法一死,才會裝載SingletonInstance類傻唾,從而完成Singleton的實例化。類的靜態(tài)屬性只會在第一次加載類的時候初始化伪煤,所以在這里凛辣,JVM幫助我們保證了線程的安全性,在類進行初始化時防泵,別的線程是無法進入的蝗敢。?
優(yōu)點:避免了線程不安全,延遲加載锁右,效率高讶泰。
代碼:
public?class?Singleton {
//私有構(gòu)造
?? ?private?Singleton() {}
//靜態(tài)內(nèi)部類
?? ?private?static?class?SingletonInstance {
?? ??? ?private?static?final?Singleton INSTANCE?=?new?Singleton();
?? ?}
?? ?public?static?Singleton getInstance() {
?? ??? ?return?SingletonInstance.INSTANCE;
?? ?}
}
8.枚舉
借助JDK1.5中添加的枚舉來實現(xiàn)單例模式痪署。不僅能避免多線程同步問題,而且還能防止反序列化重新創(chuàng)建新的對象余寥。可能是因為枚舉在JDK1.5中才添加劈狐,所以在實際項目開發(fā)中呐馆,很少見人這么寫過汹来。
代碼:
public?enum?Singleton {
?? ?INSTANCE;
?? ?public?void?whateverMethod() {
?? ?}
}
對比