【原創·教程·連載】《Android之大話設計模式》–設計模式 建立型模式 第四章:單例模式

來源:互聯網
上載者:User
<大話設計模式>本教程說明及著作權聲明

l 該文檔參考和使用了網路上的免費開放的圖片和內容,並以免費開放的方式發布,希望為移動互連網和智能手機時代貢獻綿薄之力!可以隨意轉載,但不得使用該文檔謀利。

l 如果對該文檔有任何疑問或者建議,請進入官方部落格

   http://www.cnblogs.com/guoshiandroid/留言或者直接與國士工作室聯絡(後附連絡方式),我們會謹慎參考您的建議並根據需要對本文檔進行修改,以造福更多開發人員!

l 《大話設計模式》的最新及完整內容會在國士工作室官方部落格定期更新,請訪問國士工作室部落格

http://www.cnblogs.com/guoshiandroid/擷取更多更新內容。

國士工作室是一支專註於Android平台企業級應用開發的技術團隊,致力於做中國最棒的Android應用程式開發機構,提供最棒的Android企業級應用開發培訓服務。

企業培訓和開發合作官方連絡方式:

     電話:18610086859

     Email:hiheartfirst@gmail.com

     QQ:1740415547

     QQ群:148325348

國士工作室 有你更美好!

 

 

  查看其他部分:本教程整體說明及章節索引

本文PDF下載連結

單例模式 你是我的唯一 

單例模式應用情境舉例 

        “曾經滄海難為水,除卻巫山不是雲”,這句話用現在的語言解釋就是“你是我的唯一”。

GG和MM都是初次戀愛,都把對方視為自己此生的唯一。而且GG和MM都在不斷的向對方學習,不斷的完善自己。GG和MM的甜蜜和幸福很快就轟動了整個院系。男生一般都拿GG的女朋友教育自己的女朋友說別人怎麼怎麼樣,而女生也經常拿MM的男朋友說男生該如何如何做。而且,年級輔導員還在年級會上表揚了GG和MM,說男生都應該想MM的男朋友學習,女生都應該向GG的女朋友學習!呵呵,很顯然,大家都知道,輔導員說GG的女朋友就是指MM,而說MM的男朋友時就是指GG。

單例模式解釋: 

        GoF對單例模式(Singleton Pattern)的定義是:保證一個類、只有一個執行個體存在,同時提供能對該執行個體加以訪問的全域存取方法。   

       單例模式是一種對象建立型模式,使用單例模式,可以保證為一個類只產生唯一的執行個體對象。也就是說,在整個程式空間中,該類只存在一個執行個體對象。

       單例模式的要點有三個;一是某個類只能有一個執行個體;二是它必須自行建立這個執行個體;三是它必須自行向整個系統提供這個執行個體。

英文定義為:Ensure a class only has one instance, and provide a global point of access to it.     

單例模式的UML圖: 

       單例模式比較的單純,其UML圖如下所示:

   

單例模式深入分析

       單例模式的要點有三個;一是某個類只能有一個執行個體;二是它必須自行建立這個執行個體;三是它必須自行向整個系統提供這個執行個體。

      單例模式適合於一個類只有一個執行個體的情況,比如視窗管理器,列印緩衝池和檔案系統,它們都是原型的例子。典型的情況是,那些對象的類型被遍及一個軟體系統的不同對象訪問,因此需要一個全域的訪問指標,這便是眾所周知的單例模式的應用。當然這隻有在你確信你不再需要任何多於一個的執行個體的情況下

      在電腦系統中,需要管理的資源套件括軟體外部資源,譬如每台電腦可以有若干個印表機,但只能有一個Printer Spooler, 以避免兩個列印工作同時輸出到印表機中。每台電腦可以有若干傳真卡,但是只應該有一個軟體負責管理傳真卡,以避免出現兩份傳真作業同時傳到傳真卡中的情況。每台電腦可以有若干通訊連接埠,系統應當集中管理這些通訊連接埠,以避免一個通訊連接埠同時被兩個請求同時調用。

  需要管理的資源也包括軟體內部資源,譬如,大多數的軟體都有一個(甚至多個)屬性(properties)檔案存放系統配置。這樣的系統應當由一個對象來管理一個屬性檔案。

  需要管理的軟體內部資源也包括譬如負責記錄網站來訪人數的組件,記錄軟體系統內部事件、出錯資訊的組件,或是對系統的表現進行檢查的組件等。這些組件都必須集中管理。

單例模式使用情境分析及代碼實現: 

       在上面的使用情境中,無論是誰叫GG的女朋友,大家都知道只的是MM;而相應的,無論是誰說MM的男朋友,大家都知道是GG。GG和MM分別都是對方單例O(∩_∩)O哈哈~

       UML模型圖如下所示:

      

筆者在這裡以MM的男朋友GG為例進行單例模式的說明。

GG單例模式的第一個版本,採用的是“餓漢式”,也就是當類載入進來的就立即執行個體化GG對象,但是這種方式比較的消耗電腦資源。具體實現代碼如下:

package com.diermeng.designPattern.Singleton;

/*

 * GG單例模式的第一個版本 為“餓漢式”

 */

public class GGVersionOne {

    //在類被載入進入記憶體的時候就建立單一的GG對象

    public static final GGVersionOne gGVersionOne = new GGVersionOne();

    //名稱屬性

    private String name;

 

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    //建構函式私人化

    private GGVersionOne() {

    }

 

    //提供一個全域的靜態方法

    public static GGVersionOne getGG() {

        return gGVersionOne;

    }

}

GG單例模式的第二個版本:“懶漢式”,在單線程下能夠非常好的工作,但是在多線程下存線上程安全問題,具體代碼如下:

package com.diermeng.designPattern.Singleton;

/*

 * GG單例模式的第二個版本 採用“懶漢式” 在需要使用的時候才執行個體化GG

 */

public class GGVersionTwo {

    //GG的姓名

    private String name;

    //對單例本身引用的名稱

    private static GGVersionTwo gGVersionTwo;

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    //建構函式私人化

    private GGVersionTwo() {

    }

 

    //提供一個全域的靜態方法

    public static GGVersionTwo getGG() {

        if(gGVersionTwo == null) {

            gGVersionTwo = new GGVersionTwo();

        }

        return gGVersionTwo;

    }

}

GG單例模式的第三個版本,為解決多線程問題,採用了對函數進行同步的方式,但是比較浪費資源,因為每次都要進行同步檢查,而實際中真正需要檢查只是第一次執行個體化的時候,具體代碼如下所示:

package com.diermeng.designPattern.Singleton;

/*

 * GG單例模式的第三個版本 對函數進行同步

 */

public class GGVersionThree {

    //GG的姓名

    private String name;

    //對單例本身引用的名稱

    private static GGVersionThree gGVersionThree;

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    //建構函式私人化

    private GGVersionThree() {

    }

 

    //提供一個全域的靜態方法,使用同步方法

    public static synchronized GGVersionThree getGG() {

        if(gGVersionThree == null) {

            gGVersionThree = new GGVersionThree();

        }

        return gGVersionThree;

    }

}

GG單例模式第四個版本,既解決了“懶漢式的”多線程問題,又解決了資源浪費的現象,看上去是一種不錯的選擇,具體代碼如下所示:

package com.diermeng.designPattern.Singleton;

/*

 * GG單例模式的第四個版本,既解決了“懶漢式的”多線程問題,又解決了資源浪費的現象,看上去是一種不錯的選擇

 */

public class GGVersionFour {

    //GG的姓名

    private String name;

    //對單例本身引用的名稱

    private static GGVersionFour gGVersionFour;

 

    public String getName() {

        return name;

    }

 

    public void setName(String name) {

        this.name = name;

    }

 

    //建構函式私人化

    private GGVersionFour() {

    }

 

    //提供一個全域的靜態方法

    public static GGVersionFour getGG() {

        if(gGVersionFour == null) {

            synchronized (GGVersionFour.class) {

                if(gGVersionFour == null) {

                    gGVersionFour = new GGVersionFour();

                }

            }

 

        }

        return gGVersionFour;

    }

}

最後我們建立測試用戶端測試一下版本四:

package com.diermeng.designPattern.Singleton.client;

import com.diermeng.designPattern.Singleton.GGVersionFour;

 

/*

 * 測試用戶端

 */

public class SingletonTest {

    public static void main(String[] args) {

        //執行個體化

        GGVersionFour gG1 = GGVersionFour.getGG();

        GGVersionFour gG2 = GGVersionFour.getGG();

        //設值

        gG1.setName("GGAlias");

        gG2.setName("GG");

 

        System.out.println(gG1.getName());

        System.out.println(gG2.getName());

 

 

    }

}

輸出的結果如下:

GG

GG

 

單例模式的優缺點分析: 

       優點:用戶端使用單例模式類的執行個體的時候,只需要調用一個單一的方法即可產生一個唯一的執行個體,有利於節約資源。

      缺點:首先單例模式很難實現序列化,這就導致採用單例模式的類很難被持久化,當然也很難通過網路傳輸;其次由於單例採用靜態方法,無法在繼承結構中使用。最後如果在分布式叢集的環境中存在多個Java虛擬機器的情況下,具體確定哪個單例在運行也是很困難的事情。

單例模式的實際應用簡介: 

單例模式一般會出現在以下情況下: 

在多個線程之間,比如servlet環境,共用同一個資源或者操作同一個對象

在整個程式空間使用全域變數,共用資源

大規模系統中,為了效能的考慮,需要節省對象的建立時間等等。

溫馨提示: 

       細心的讀者可能會發現,筆者在寫單例模式的雙重檢查方式的使用了“看上去是一種不錯的選擇”之語,之所以樣說,是因為:Java的線程工作順序是不確定的,這就會導致在多線程的情況沒有執行個體化就使用的現象,進而導致程式崩潰。不過雙重檢查在C語言中並沒有問題。因為大師說:雙重檢查對Java語言並不是成立的。儘管如此,雙重檢查仍然不失為解決多線程情況下單例模式的一種理想的方案。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.