www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

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

單例模式

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

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

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

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

單線程中:

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

這樣就可以了,保證只取得了一個實(shí)例。但是在多線程的環(huán)境下卻不行了,因?yàn)楹芸赡軆蓚€線程同時運(yùn)行到if (instance == NULL)這一句,導(dǎo)致可能會產(chǎn)生兩個實(shí)例。于是就要在代碼中加鎖。

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

    return instance;
}

但這樣寫的話,會稍稍映像性能,因?yàn)槊看闻袛嗍欠駷榭斩夹枰绘i定,如果有很多線程的話,就愛會造成大量線程的阻塞。于是出現(xiàn)了雙重鎖定。

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

    return instance;
}

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

常用的場景

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

優(yōu)點(diǎn)

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

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

缺點(diǎn)

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

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

?

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

private:
    Singleton();
    //把復(fù)制構(gòu)造函數(shù)和=操作符也設(shè)為私有,防止被復(fù)制
    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ù)的類型,其它帶參數(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的實(shí)現(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)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機(jī)作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計(jì)中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計(jì)成為提升電機(jī)驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機(jī) 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實(shí)際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗(yàn)。要解決這一問題,需從設(shè)計(jì)、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計(jì) 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機(jī)驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機(jī)驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨(dú)特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計(jì)工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機(jī)重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉