<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    模式回顧---單例

    最近突然想回顧一下設計模式,很多東西是要回過頭來總結一下的。今天先回顧一下單例吧。
    很多時候覺得挺搞笑的,去面試的時候如果人家問你設計模式,一般都是要你寫個單例模式。去年來北京好幾家面試都是問我這個。當時我就想這個能反映出一個人的水平來嗎?還是說更多的是反映出這個公司的水平呢?
    隨著一年的應用,很多地方都用過之后覺得,單例這個東西雖然簡單,可是現(xiàn)實是復雜的。所以單例這個簡單的模式也不能太小瞧咯。
    單例其實有很多種實現(xiàn),這是其中的一種,延遲加載的(好像英文叫Lazy?):
    [下面代碼中所有的構造器都是私有的,這里我就省略不寫了。]
    public class ClassName {
        
    public static ClassName getInstance(){
            
    if(instance == null)
            {
                instance 
    = new ClassName();
            }
            
    return instance;
        }
        
        
    private static ClassName instance;
    }
    這種的好處是我們的單例使用時才進行初始化,這樣方便我們在系統(tǒng)啟動時做些小動作。但是這個方式不是線程安全的,想要完成一個線程安全的單例,有幾種方式:
    (一)
    public class ClassName {
        
    public static ClassName getInstance(){
            
    return instance;
        }
        
        
    private static ClassName instance = new ClassName();
    }
    這種方式,可以保證我們的單例是線程安全的,畢竟我們唯一的實例在系統(tǒng)初始化的時候就構造了。可是Java的機制是static級別的變量初始化時互相調用是會報異常的。所以隨著系統(tǒng)的擴展,尤其還會有一些新手或者粗心大意的家伙(比如說,我)會亂用你的方法。一不小心就造成問題了。而且,你也失去了第一個方式中的一個小優(yōu)勢,不能在系統(tǒng)啟動時做點小動作了。
    (二)
    public class ClassName {
        
    public static synchronized ClassName getInstance(){
            
    if(instance == null)
            {
                 instance 
    = new ClassName();
            }
            
    return instance;
        }
        
        
    private static ClassName instance;
    }
    這樣倒是線程安全了,也可以延遲加載,但是從今以后這個getInstance方法就是synchronized的了,那絕對是很影響效率的。我跟朋友討論提出了幾種寫法,以期既能使單例可以在系統(tǒng)啟動不至于數(shù)據(jù)已經(jīng)煮成熟飯又是線程安全的:(少數(shù)人討論結果,代碼可能會比較丑陋,僅供參考,歡迎拍磚)

    public class ClassName {
        
    public static ClassName getInstance(){
            
    if(instance == null)
            {
                 instance 
    = ClassName.createInstance();
            }
            
    return instance;
        }
        
        
    private static synchronized ClassName createInstance(){
            
    if(instance == null)
            {    
                
    return new ClassName();
            }
    else{
                
    return instance;
            }
        }
        
        
    private static ClassName instance;
    }
    這種寫法就很好的解決了這些問題。
    還有一種寫法是這樣的,這個不是延遲加載的。而是采用了一種取巧的方式。
    public class ClassName {
        
    public static ClassName getInstance(){
            
    if(!instance.isInit)
            {
                 instance.initSingleton();
            }
            
    return instance;
        }
        
        
    private synchronized void initSingleton() {
          
    if(!isInit)
          {
              reset();
    //這名字是有點怪異,我沒時間想太好聽的名字
              isInit = true;
          }
        }
        
        
    public void  reset(){
            
    //.....真正進行數(shù)據(jù)初始化的地方
        }
        
        
    private boolean isInit = false;
        
        
    private static ClassName instance = new ClassName();
    }

    將所有的初始化代碼搬到構造器之外。這是專為數(shù)據(jù)初始化和復位進行的設計。所以我把reset開放了出來。



    posted on 2008-01-29 21:59 咖啡屋的鼠標 閱讀(1459) 評論(7)  編輯  收藏 所屬分類: Java

    評論

    # re: 模式回顧---單例 2008-01-30 09:30 久城

    我一般用的都是這種:
    public class ClassName {
    public static ClassName getInstance(){
    if(instance == null)
    {
    instance = new ClassName();
    }
    return instance;
    }

    private static ClassName instance;
    }  回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 10:05 大衛(wèi)

    不錯!  回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 10:51 dennis

    public class ClassName {
    public static ClassName getInstance(){
    if(instance == null)
    {
    instance = ClassName.createInstance();
    }
    return instance;
    }

    private static synchronized ClassName createInstance(){
    return new ClassName();
    }

    private static ClassName instance;
    }
    這種寫法有問題的,可以想象下,線程A判斷instance==null,然后開始createInstance,正在此時,線程B也判斷instance==null,然后等待線程A完成創(chuàng)建并解鎖,然后線程B也createInstance,這還是單例嗎?單例模式的寫法網(wǎng)上已經(jīng)討論爛了,這樣的錯誤實在不應該。  回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 10:52 dennis

    第三種寫法就更無語了,靜態(tài)初始化,更談不上所謂的lazy initialize了。基礎還是好好看下吧。  回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 10:54 dennis

    ps:我所說的第三種是最后那個。
    既然發(fā)表在blogjava首頁上,文章至少要保證沒有錯誤,不然誤導人也是害人害己,說的嚴重了,博主自己看看。  回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 11:45 咖啡屋的鼠標

    @dennis
    感謝您的批評指正,這個寫法是有點問題。昨天跟朋友討論出這個方法的時候沒考慮細,剛才看了看,改改也能使用,可能就丑陋點了。先刪去。

    至于最后一種,確實不是lazy的,我看了看也沒寫是Lazy的,應該不會有誤導概念的問題,但還是標明了一下以防止誤會,很感謝你的指出。我只是把所有的初始化代碼放到了init里面,在構造器里不做任何操作初始化操作,其實還應該做一次是否初始化的二次判斷。省的多次初始化,但是那樣我就還要再寫一個函數(shù)來控制復位,說起來可能會更繁瑣,就沒加。

      回復  更多評論   

    # re: 模式回顧---單例 2008-01-30 13:18 咖啡屋的鼠標

    考慮了一下,還是趁中午的時間把改正的結果更新了,經(jīng)過簡單的多線程測試是沒有問題的。  回復  更多評論   


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    <2008年1月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    導航

    統(tǒng)計

    常用鏈接

    留言簿(15)

    隨筆分類(52)

    隨筆檔案(76)

    文章分類(3)

    文章檔案(4)

    新聞檔案(1)

    收藏夾

    Flex

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 日本亚洲成高清一区二区三区| 91亚洲国产成人久久精品网站| av午夜福利一片免费看久久| 亚洲AV无码乱码国产麻豆穿越| 亚洲黄色免费观看| 看Aⅴ免费毛片手机播放| 国产成人A亚洲精V品无码| 很黄很黄的网站免费的| 美女黄频免费网站| 91亚洲国产在人线播放午夜| 国产成人精品免费视频软件| a毛片免费观看完整| 中文日韩亚洲欧美制服| 亚洲人妻av伦理| 久草在视频免费福利| 一个人免费观看视频在线中文 | xxxxxx日本处大片免费看| 久久久久亚洲AV无码永不| 日韩精品视频免费在线观看| 全免费a级毛片免费看| 亚洲av日韩精品久久久久久a| 国产∨亚洲V天堂无码久久久| 女人18毛片水真多免费播放| 精品四虎免费观看国产高清午夜| 亚洲日韩中文字幕无码一区| 亚洲VA中文字幕不卡无码| 精品久久久久久久免费加勒比| 黄网站色视频免费在线观看的a站最新| 国产精品亚洲四区在线观看| 狠狠亚洲婷婷综合色香五月排名| 免费理论片51人人看电影| 91青青国产在线观看免费| 国产日韩AV免费无码一区二区三区 | kk4kk免费视频毛片| 午夜在线a亚洲v天堂网2019| 亚洲av中文无码乱人伦在线播放| 免费人妻av无码专区| 久久精品女人天堂AV免费观看| 无码人妻一区二区三区免费看 | 亚洲精品A在线观看| 午夜网站免费版在线观看|