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

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

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

    模式回顧---單例

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

    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(){
            
    //.....真正進行數據初始化的地方
        }
        
        
    private boolean isInit = false;
        
        
    private static ClassName instance = new ClassName();
    }

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



    posted on 2008-01-29 21:59 咖啡屋的鼠標 閱讀(1446) 評論(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 大衛

    不錯!  回復  更多評論   

    # 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完成創建并解鎖,然后線程B也createInstance,這還是單例嗎?單例模式的寫法網上已經討論爛了,這樣的錯誤實在不應該。  回復  更多評論   

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

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

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

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

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

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

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

      回復  更多評論   

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

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


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


    網站導航:
     
    <2008年1月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272829303112
    3456789

    導航

    統計

    常用鏈接

    留言簿(15)

    隨筆分類(52)

    隨筆檔案(76)

    文章分類(3)

    文章檔案(4)

    新聞檔案(1)

    收藏夾

    Flex

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 337p日本欧洲亚洲大胆人人| 一级毛片一级毛片免费毛片 | mm1313亚洲国产精品美女| 亚洲国产成人精品无码久久久久久综合| 亚洲国产一二三精品无码| 亚洲高清无在码在线无弹窗| 亚洲一区二区三区写真| 亚洲精品视频免费| 免费看污成人午夜网站| 在线a亚洲v天堂网2019无码| 午夜在线a亚洲v天堂网2019| 免费无码作爱视频| 国产猛烈高潮尖叫视频免费| 亚洲爆乳无码专区| 精品成人一区二区三区免费视频| 最近中文字幕大全免费视频| 免费亚洲视频在线观看| 亚洲w码欧洲s码免费| 黄色网址在线免费| 国产网站免费观看| 免费无码国产在线观国内自拍中文字幕 | 日韩激情淫片免费看| 亚洲精品人成电影网| 两性色午夜视频免费网| 日韩免费视频一区| 九九九精品视频免费| 亚洲国产精品无码久久久不卡 | 久久久久久亚洲av无码蜜芽| 一区二区三区四区免费视频| 亚洲精品综合久久| 亚洲人成小说网站色| 免费国产不卡午夜福在线| 国产一级a毛一级a看免费人娇| 亚洲第一成年网站大全亚洲| 成年女人18级毛片毛片免费| 亚洲精品无码久久毛片波多野吉衣| 成人毛片视频免费网站观看| 国产久爱免费精品视频| 在线亚洲97se亚洲综合在线| 182tv免费观看在线视频| 337p日本欧洲亚洲大胆色噜噜|