當前位置:首頁 > 芯聞號 > 充電吧
[導讀]單例模式 單例模式,可以說設(shè)計模式中最常應(yīng)用的一種模式了,據(jù)說也是面試官最喜歡的題目。但是如果沒有學過設(shè)計模式的人,可能不會想到要去應(yīng)用單例模式,面對單例模式適用的情況,可能會優(yōu)先考慮使用全局或者靜

單例模式

單例模式,可以說設(shè)計模式中最常應(yīng)用的一種模式了,據(jù)說也是面試官最喜歡的題目。但是如果沒有學過設(shè)計模式的人,可能不會想到要去應(yīng)用單例模式,面對單例模式適用的情況,可能會優(yōu)先考慮使用全局或者靜態(tài)變量的方式,這樣比較簡單,也是沒學過設(shè)計模式的人所能想到的最簡單的方式了。

一般情況下,我們建立的一些類是屬于工具性質(zhì)的,基本不用存儲太多的跟自身有關(guān)的數(shù)據(jù),在這種情況下,每次都去new一個對象,即增加了開銷,也使得代碼更加臃腫。其實,我們只需要一個實例對象就可以。如果采用全局或者靜態(tài)變量的方式,會影響封裝性,難以保證別的代碼不會對全局變量造成影響。

考慮到這些需要,我們將默認的構(gòu)造函數(shù)聲明為私有的,這樣就不會被外部所new了,甚至可以將析構(gòu)函數(shù)也聲明為私有的,這樣就只有自己能夠刪除自己了。在Java和C#這樣純的面向?qū)ο蟮恼Z言中,單例模式非常好實現(xiàn),直接就可以在靜態(tài)區(qū)初始化instance,然后通過getInstance返回,這種就被稱為餓漢式單例類。也有些寫法是在getInstance中new instance然后返回,這種就被稱為懶漢式單例類,但這涉及到第一次getInstance的一個判斷問題。

下面的代碼只是表示一下,跟具體哪種語言沒有關(guān)系。

單線程中:

Singleton* getInstance()
{
    if (instance == NULL)
        instance = new Singleton();
 
    return instance;
}

這樣就可以了,保證只取得了一個實例。但是在多線程的環(huán)境下卻不行了,因為很可能兩個線程同時運行到if (instance == NULL)這一句,導致可能會產(chǎn)生兩個實例。于是就要在代碼中加鎖。

Singleton* getInstance()
{
    lock();
    if (instance == NULL)
    {
       instance = new Singleton();
    }
    unlock();

    return instance;
}

但這樣寫的話,會稍稍映像性能,因為每次判斷是否為空都需要被鎖定,如果有很多線程的話,就愛會造成大量線程的阻塞。于是出現(xiàn)了雙重鎖定。

Singleton* getInstance()
{
    if (instance == NULL)
    {
    lock();
        if (instance == NULL)
        {
               instance = new Singleton();
        }
        unlock();
    }

    return instance;
}

這樣只夠極低的幾率下,通過越過了if (instance == NULL)的線程才會有進入鎖定臨界區(qū)的可能性,這種幾率還是比較低的,不會阻塞太多的線程,但為了防止一個線程進入臨界區(qū)創(chuàng)建實例,另外的線程也進去臨界區(qū)創(chuàng)建實例,又加上了一道防御if (instance == NULL),這樣就確保不會重復創(chuàng)建了。

常用的場景

單例模式常常與工廠模式結(jié)合使用,因為工廠只需要創(chuàng)建產(chǎn)品實例就可以了,在多線程的環(huán)境下也不會造成任何的沖突,因此只需要一個工廠實例就可以了。

優(yōu)點

1.減少了時間和空間的開銷(new實例的開銷)。

2.提高了封裝性,使得外部不易改動實例。

缺點

1.懶漢式是以時間換空間的方式。(上面使用的方式)

2.餓漢式是以空間換時間的方式。(下面使用的方式)

?

#ifndef _SINGLETON_H_
#define _SINGLETON_H_
class Singleton{
public:
    static Singleton* getInstance();

private:
    Singleton();
    //把復制構(gòu)造函數(shù)和=操作符也設(shè)為私有,防止被復制
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);

    static Singleton* instance;
};

#endif

#include "Singleton.h"

Singleton::Singleton(){

}

Singleton::Singleton(const Singleton&){

}

Singleton& Singleton::operator=(const Singleton&){

}

//在此處初始化
Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::getInstance(){
    return instance;
}

#include "Singleton.h"
#include 

int main(){
    Singleton* singleton1 = Singleton::getInstance();
    Singleton* singleton2 = Singleton::getInstance();

    if (singleton1 == singleton2)
        fprintf(stderr,"singleton1 = singleton2n");

    return 0;
}

?

以上使用的方式存在問題:只能實例化沒有參數(shù)的類型,其它帶參數(shù)的類型就不行了。

c++11 為我們提供了解決方案:可變模板參數(shù)

template 
class Singleton
{
public:
template
  static T* Instance(Args&&... args)
  {
        if(m_pInstance==nullptr)
            m_pInstance = new T(std::forward(args)...);
        return m_pInstance;
    }
  static T* GetInstance()
      {
            if (m_pInstance == nullptr)
               { 
?                  const char * className = typeid(T).name();
?                  QString fatal = "Singleton qFatal:
<<"+QString(QLatin1String(className))+">> repeat init"                  throw std::logic_error("the instance is not init, please initialize the instance first");
               }
                  
            return m_pInstance;
      }
static void DestroyInstance()
    {
        delete m_pInstance;
        m_pInstance = nullptr;
    }

private:
        Singleton(void);
        virtual ~Singleton(void);
        Singleton(const Singleton&);
        Singleton& operator = (const Singleton&);
private:
    static T* m_pInstance;
};

template  T*  Singleton::m_pInstance = nullptr;

由于原來的接口中,單例對象的初始化和取值都是一個接口,可能會遭到誤用,更新之后,講初始化和取值分為兩個接口,單例的用法為:先初始化,后面取值,如果中途銷毀單例的話,需要重新取值。如果沒有初始化就取值則會拋出一個異常。

Multiton的實現(xiàn)

#include 
#include 
#include 
using namespace std;

template < typename T, typename K = string>
class Multiton
{
public:
    template
    static std::shared_ptr Instance(const K& key, Args&&... args)
    {
        return GetInstance(key, std::forward(args)...);
    }

    template
    static std::shared_ptr Instance(K&& key, Args&&... args)
    {
        return GetInstance(key, std::forward(args)...);
    }
private:
    template
    static std::shared_ptr GetInstance(Key&& key, Args&&...args)
    {
        std::shared_ptr instance = nullptr;
        auto it = m_map.find(key);
        if (it == m_map.end())
        {
            instance = std::make_shared(std::forward(args)...);
            m_map.emplace(key, instance);
        }
        else
        {
            instance = it->second;
        }

        return instance;
    }

private:
    Multiton(void);
    virtual ~Multiton(void);
    Multiton(const Multiton&);
    Multiton& operator = (const Multiton&);
private:
    static map> m_map;
};

template 
map> Multiton::m_map;
本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉