<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

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 四虎精品亚洲一区二区三区| 无码日韩精品一区二区免费| 亚洲成A人片77777国产| 亚洲欧美国产精品专区久久| 免费精品国偷自产在线在线| 亚洲毛片一级带毛片基地| 色老头永久免费网站| 亚洲成a人片在线观| 3d动漫精品啪啪一区二区免费| 久久亚洲日韩看片无码| 99久9在线|免费| 亚洲精品成人久久| 成年女人视频网站免费m| 亚洲AV成人精品一区二区三区| 国产在线不卡免费播放| 免费看又黄又爽又猛的视频软件 | 免费在线观看h片| 亚洲六月丁香六月婷婷色伊人| 成人免费黄色网址| 亚洲av永久无码天堂网| 亚洲国产一区视频| 黄色网页在线免费观看| 亚洲国产成人精品不卡青青草原| 亚洲三级在线免费观看| 无码一区二区三区亚洲人妻| 亚洲熟妇无码八AV在线播放| 久久www免费人成看片| 国产精品亚洲专区无码牛牛| 在线观看亚洲成人| 91精品国产免费久久国语蜜臀 | 亚洲成A人片在线播放器| 国产精品四虎在线观看免费| 久久www免费人成精品香蕉| 亚洲嫩草影院久久精品| 成人免费无码大片A毛片抽搐色欲 成人免费无码大片a毛片 | 18禁止观看免费私人影院| 亚洲第一综合天堂另类专| 77777亚洲午夜久久多人| 最近中文字幕2019高清免费| 羞羞视频免费观看| 亚洲色欲色欲综合网站|