久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

設(shè)計模式之單例模式

 dongsibei 2014-05-12

1         單例模式的日常應(yīng)用

我們在瀏覽BBSSNS網(wǎng)站的時候,常常會看到“當(dāng)前在線人數(shù)”這樣的一項內(nèi)容。對于這樣的一項功能,我們通常的做法是把當(dāng)前的在線人數(shù)存放到一個內(nèi)存、文件或者數(shù)據(jù)庫中,每次用戶登錄的時候,,就會馬上從內(nèi)存、文件或者數(shù)據(jù)庫中取出,,在其基礎(chǔ)上加1后,,作為當(dāng)前的在線人數(shù)進行顯示,然后再把它保存回內(nèi)存,、文件或者數(shù)據(jù)庫里,,這樣后續(xù)登錄的用戶看到的就是更新后的當(dāng)前在線人數(shù);同樣的道理,,當(dāng)用戶退出后,,當(dāng)前在線人數(shù)進行減1的工作。所以,,對于這樣的一個需求,,我們按照面向?qū)ο蟮脑O(shè)計思想,可以把它抽象為“在線計數(shù)器”這樣一個對象,,具體實現(xiàn)如下:

Java代碼:

class OnlineCounter {

    private int onlineCount = 0;

    public OnlineCounter(){

,假如讀出來的數(shù)據(jù)是       this.onlineCount = 100;

    //在用戶登錄后,,在線人數(shù)加    public void incCount(){

    }

1

       this.onlineCount--;

    //保存在線人數(shù)

}  

    public int getCount(){

    }

    public static void main(String[] args) {

       OnlineCounter onlineCounter = new OnlineCounter();

<FONT style="FONT-SIZE: 10pt" color="black" face=""">       System.out.println("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" +onlineCounter.getCount());

       System.out.println("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" + onlineCounter.getCount());

       System.out.println("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" + onlineCounter.getCount());

       }

}

.Net代碼:

class OnlineCounter{

    private int onlineCount = 0;

    public OnlineCounter(){

,假如讀出來的數(shù)據(jù)是        this.onlineCount = 100;

    //在用戶登錄后,在線人數(shù)加    public void incCount(){

    }

1

        this.onlineCount--;

//保存在線人數(shù)

        return onlineCount;

    //獲取在線人數(shù)

        return onlineCount;

    //測試函數(shù)

        OnlineCounter onlineCounter = new OnlineCounter();

<FONT style="FONT-SIZE: 10pt" color="black" face=""">        Console.WriteLine("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" + onlineCounter.getCount());

        Console.WriteLine("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" + onlineCounter.getCount());

        Console.WriteLine("在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" + onlineCounter.getCount());

}

<?php

class OnlineCounter {

    private $onlineCount = 0;

    public function __construct(){

,假如讀出來的數(shù)據(jù)是       $this->onlineCount = 100;

    //在用戶登錄后,,在線人數(shù)加    public function incCount(){

    }

1

       $this->onlineCount--;

//保存在線人數(shù)

    }

    public function getCount(){

    }

    public static function execute() {

       echo "在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" . $onlineCounter->getCount();

       echo "在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" . $onlineCounter->getCount();

       echo "在線人數(shù):<FONT style="FONT-SIZE: 10pt" color="black" face=""">" . $onlineCounter->getCount();

}

?>

運行結(jié)果如下:

在線人數(shù):101

在線人數(shù):class Singleton {

    private static Singleton instance = null;

    private Singleton (){

    // 公開的靜態(tài)工廠方法   public static Singleton getInstance(){

            instance = new Singleton();

        return instance;

}

.Net代碼:

    // 私有的靜態(tài)對象

" p="" style="TEXT-ALIGN: left; MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none" class="MsoNormal" align="left" font="" style="FONT-SIZE: 10pt" color="black" face="">    //私有的構(gòu)造方法

    }

,返回此類的唯一實例

        if (instance == null){

        }

    }

<?php

    // 私有的靜態(tài)對象

" p="" style="TEXT-ALIGN: left; MARGIN: 0cm 0cm 0pt; mso-layout-grid-align: none" class="MsoNormal" align="left" font="" style="FONT-SIZE: 10pt" color="black" face="">    //私有的構(gòu)造方法

    }

,返回此類的唯一實例

        if(self::$instance == null){

        }

    }

?>

Singleton類含有一個instance的私有靜態(tài)變量,用來保存該類唯一的實例對象,,它對于外部對象是不可見的,只能通過getInstance方法才能獲得,。

Singleton類的構(gòu)造器是private私有的,,外部對象無法通過它的構(gòu)造器生成實例,也就是說外部程序試圖通過new操作符來創(chuàng)建實例是行不通的,,因此,,getInstance方法成為獲得Singleton類實例的唯一途徑。

getInstance方法的設(shè)計非常簡單,,它首先檢測instance變量是否已經(jīng)初始化,,如果沒有被初始化,,就創(chuàng)建一個實例保存到instance變量,最后返回這個實例,;如果這個實例已經(jīng)被初始化,,那么就直接返回這個實例。

getInstance方法的設(shè)計非常簡單,,它首先檢測instance變量是否已經(jīng)初始化,,如果沒有被初始化,就創(chuàng)建一個實例保存到instance變量,,最后返回這個實例,;如果這個實例已經(jīng)被初始化,那么就直接返回這個實例,。

 

 

 

單例模式的類圖

 

單例模式主要有3個特點,:

1,、單例類確保自己只有一個實例,。

2、單例類必須自己創(chuàng)建自己的實例,。

3,、單例類必須為其他對象提供唯一的實例。

3         安全的單例模式:雙重檢查鎖定機制

我們雖然實現(xiàn)了單例模式,,但是目前的解決辦法并不安全,,依然存在著一定的缺陷:

    private static Singleton instance = null;

}

        if(instance == null){

        }

    }

instance = null;

private Singleton() {

}

public static Singleton getInstance(){

    1,第instance

if (//位置n個線程到達

synchronized (this)

{

3,,任何時間只能有instance == null) 4,,第instance

{

instance;   

}   

}

.Net代碼:

private static Singleton instance = null;

private Singleton (){

public static Singleton getInstance(){

1,第instance

//位置n個線程到達

{

3,,任何時間只能有instance == null) 4,,第instance

{

}

        }

    }

instance = new Singleton()語句,instance對象,。

5)線程B 進入synchronized(this)塊,,到達位置3,進而到達位置4,。由于instance,,這時候的<FONT style="LINE-HEIGHT: 115%; FONT-SIZE: 10pt" color="black" face=""">instance只有一個

我們通過兩次檢查instance是否被實例化來解決線程安全問題,,這種處理方式稱為雙重檢查鎖定機制(Double-checked locking),。還有另外一種解決線程安全的方法,就是把getInstance方法整體作為同步區(qū),,比如聲明為public static synchronized Singleton getInstance(),,這種方式由于鎖定的區(qū)域過大,,特殊情況下會造成系統(tǒng)性能的下降,成為系統(tǒng)的性能瓶頸,。

雙重檢查鎖定機制不僅解決了線程安全問題,,而且把性能也處理得很不錯,看起來非常完美,。不幸的是我們應(yīng)該注意不要在java中使用雙重檢查鎖定機制,,由于Java編譯器和 JIT 的優(yōu)化的原因,系統(tǒng)無法保證我們期望的執(zhí)行次序,。雖然Java語法中的volatile修飾符可以強制屏蔽編譯器和 JIT 的優(yōu)化工作,,但它是一種非常脆弱的同步機制,比較難以控制,,所以建議盡量減少使用,。我們后面還提供了其它的一種實現(xiàn)方式。

4         單例模式的實現(xiàn)方式:懶漢單例類和餓漢單例類

單例模式的實現(xiàn)有多種方法,,常見的就有懶漢式單例類和餓漢式單例類,。我們前面介紹的實現(xiàn)方法就屬于懶漢式單例類。

l         懶漢式單例類

對于懶漢模式,,我們可以這樣理解:該單例類非常懶,,只有在自身需要的時候才會行動,從來不知道及早做好準(zhǔn)備,。它在需要對象的時候,,才判斷是否已有對象,如果沒有就立即創(chuàng)建一個對象,,然后返回,,如果已有對象就不再創(chuàng)建,立即返回,。

懶漢模式只在外部對象第一次請求實例的時候才去創(chuàng)建,。

l         餓漢式單例

對于餓漢模式,我們可以這樣理解:該單例類非常餓,,迫切需要吃東西,,所以它在類加載的時候就立即創(chuàng)建對象。

Java代碼:

final class Singleton {

     //私有的唯一實例成員,在類加載的時候就創(chuàng)建好了單例對象

     private static final Singleton instance = new Singleton();

     //私有的構(gòu)造方法,避免外部創(chuàng)建類實例

     private Singleton() {

     }

     //靜態(tài)工廠方法,返回此類的唯一實例

     public static Singleton getInstance() {

         return instance;

     }

}

.Net代碼:

sealed class Singleton {

     //私有的唯一實例成員,在類加載的時候就創(chuàng)建好了單例對象

     private static readonly Singleton instance = new Singleton();

     //私有的構(gòu)造方法,避免外部創(chuàng)建類實例

     private Singleton() {

     }

     //靜態(tài)工廠方法,返回此類的唯一實例

     public static Singleton getInstance() {

         return instance;

     }

}

使用Java中的final關(guān)鍵字和.Netsealed關(guān)鍵字去修飾class,,目的是阻止派生子類,,而派生子類可能會導(dǎo)致實例不唯一。使用Java中的final關(guān)鍵字和.Netreadonly關(guān)鍵字去修飾變量,,就意味著只能在類初始化時或者在構(gòu)造器中分配該變量,。

我們對比一下懶漢模式和餓漢模式的優(yōu)缺點:

這兩種模式對于初始化較快,占用資源少的輕量級對象來說,,沒有多大的性能差異,,選擇懶漢式還是餓漢式都沒有問題,。但是對于初始化慢,占用資源多的重量級對象來說,,就會有比較明顯的差別了,。所以,對重量級對象應(yīng)用餓漢模式,,類加載時速度慢,,但運行時速度快;懶漢模式則與之相反,,類加載時速度快,,但運行時第一次獲得對象的速度慢。

 

這兩種模式對于初始化較快,,占用資源少的對象來說,,沒有多大的性能差異,但是對于初始化慢,,占用資源多的對象來說就會有比較明顯的差別了,。所以,對重量級對象應(yīng)用餓漢模式,,在類加載時需要較長時間,但運行時會有明顯的時間效率的提升,。對重量級對象應(yīng)用懶漢模式,,在類加載時很快,但至少第一次獲得對象時需要等待很長時間,。

從用戶體驗的角度來說,,我們應(yīng)該首選餓漢模式。我們愿意等待某個程序花較長的時間初始化,,卻不喜歡在程序運行時等待太久,,給人一種反應(yīng)遲鈍的感覺,所以對于有重量級對象參與的單例模式,,我們推薦使用餓漢模式,。

而對于初始化較快的輕量級對象來說,選用哪種方法都可以,。如果一個應(yīng)用中使用了大量單例模式,,我們就應(yīng)該權(quán)衡兩種方法了。輕量級對象的單例采用懶漢模式,,減輕加載時的負擔(dān),,縮短加載時間,提高加載效率,;同時由于是輕量級對象,,把這些對象的創(chuàng)建放在使用時進行,,實際就是把創(chuàng)建單例對象所消耗的時間分?jǐn)偟秸麄€應(yīng)用中去了,對于整個應(yīng)用的運行效率沒有太大影響,。

5         什么情況下使用單例模式

單例模式也是一種比較常見的設(shè)計模式,,它到底能帶給我們什么好處呢?其實無非是三個方面的作用:

第一,、控制資源的使用,,通過線程同步來控制資源的并發(fā)訪問;

第二,、控制實例產(chǎn)生的數(shù)量,,達到節(jié)約資源的目的。

第三,、作為通信媒介使用,,也就是數(shù)據(jù)共享,它可以在不建立直接關(guān)聯(lián)的條件下,,讓多個不相關(guān)的兩個線程或者進程之間實現(xiàn)通信,。

比如,數(shù)據(jù)庫連接池的設(shè)計一般采用單例模式,,數(shù)據(jù)庫連接是一種數(shù)據(jù)庫資源,。軟件系統(tǒng)中使用數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關(guān)閉數(shù)據(jù)庫連接所引起的效率損耗,,這種效率上的損耗還是非常昂貴的,。當(dāng)然,使用數(shù)據(jù)庫連接池還有很多其它的好處,,可以屏蔽不同數(shù)據(jù)數(shù)據(jù)庫之間的差異,,實現(xiàn)系統(tǒng)對數(shù)據(jù)庫的低度耦合,也可以被多個系統(tǒng)同時使用,,具有高可復(fù)用性,,還能方便對數(shù)據(jù)庫連接的管理等等。數(shù)據(jù)庫連接池屬于重量級資源,,一個應(yīng)用中只需要保留一份即可,,既節(jié)省了資源又方便管理,。所以數(shù)據(jù)庫連接池采用單例模式進行設(shè)計會是一個非常好的選擇,。

在我們?nèi)粘J褂玫脑?span lang="EN-US">Windows中也有不少單例模式設(shè)計的組件,象常用的文件管理器,。由于Windows操作系統(tǒng)是一個典型的多進程多線程系統(tǒng),,那么在創(chuàng)建或者刪除某個文件的時候,,就不可避免地出現(xiàn)多個進程或線程同時操作一個文件的現(xiàn)象。采用單例模式設(shè)計的文件管理器就可以完美的解決這個問題,所有的文件操作都必須通過唯一的實例進行,,這樣就不會產(chǎn)生混亂的現(xiàn)象,。

再比如,每臺計算機可以有若干個打印機,,如果每一個進程或者線程都獨立地使用打印機資源的話,,那么我們打印出來的結(jié)果就有可能既包含這個打印任務(wù)的一部分,又包含另外一個打印任務(wù)的一部分,。所以,,大多數(shù)的操作系統(tǒng)最終為打印任務(wù)設(shè)計了一個單例模式的假脫機服務(wù)Printer Spooler,所有的打印任務(wù)都需要通過假脫機服務(wù)進行,。

實際上,,配置信息類、管理類,、控制類,、門面類、代理類通常被設(shè)計為單例類,。像JavaStruts,、Spring框架,.NetSpring.Net框架,,以及PhpZend框架都大量使用了單例模式,。

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多