常見的設計模式:
介面卡模式、迭代器模式、工廠模式、單例模式、生成器模式、裝飾器模式、門面模式、**模式、橋接模式
介面卡模式
在之前學習棧和佇列時,我們發現棧和佇列的底層,並非自己實現,而是通過呼叫棧和佇列(庫中預設是雙端佇列)來實現的;以棧為例:我們在使用時不在乎,棧的底層實現,只要它能夠滿足尾插和尾刪即可。通過這種方法,更好的體現了stl庫的良好的復用性
迭代器模式
迭代器是stl庫中演算法和容器的紐帶,使用迭代器便可以用同一種方法對不同的容器進行訪問;迭代器類似與指標。迭代器的存在很好的保護了,物件導向的封裝性,減少了使用成本。
假如在沒有迭代器的情況下,如果要訪問紅黑樹的某乙個結點時,就必須滿足以下條件:
1、必須把其根節點暴露出來(這樣破壞了其的封裝性)
2、樹的訪問往往是通過遍歷來實現,不能直接訪問某個結點
3、要訪問某個結點,必須了解其底層實現(學習成本太大,不夠方便)
乙個類始終只能建立乙個例項,則這個類被稱為單例類,這種模式就被稱為單例模式。(執行緒安全且高效)
方法一、不考慮執行緒安全
#define _crt_secure_no_warnin 1
#pragma once
class singleton
return _inst;
} void print()
private:
singleton() //必須自己定義建構函式,且設為私有
:_a(0) //1.防止呼叫預設的建構函式 2、防止利用建構函式建立物件
singleton(const singleton&); //防拷貝,只宣告不定義
singleton& operator=(const singleton&); //防止進行深淺拷貝
private:
int _a;
static singleton* _inst; //靜態變數全域性只存乙份 ,此處的變數可以是 threadpool memorypool
};singleton* singleton:: _inst = null; //靜態變數必須在類外面,進行初始化
注意:
單例類的名字可以根據實際使用適當的名字,而非只能使用singleton;
單例類中的變數可以是執行緒池、記憶體池等(全域性只有乙份)等;
賦值運算子的過載不一定要設為私有,只在在一些情況下會存在深淺拷貝問題,因此最好設為私有;
方法二、考慮執行緒安全
上面所實現的單例類,在多執行緒的情況下,會出現執行緒安全問題
主要是由於下面的**引起:
static singleton* getinstance()
return _inst;
}
在多核情況下:
當多個執行緒同時執行這段**時,每個執行緒都建立了乙個物件;這樣便不是全域性唯一的例項物件了;
在只有乙個cpu 的情況下:
說明:每乙個被cpu排程的執行緒,只能在時間片內執行;
由於以上**不是原子的,假設有兩個執行緒執行上述**:
首先執行緒一被排程 :在執行完 if(_inst == null) ,時間片用完了;這時執行緒二被排程: 在執行完 new singleton ,時間片用完了;執行緒一被再次排程,會執行 _inst = new singleton ,那麼此時執行緒一建立了乙個物件,並且執行緒二建立的物件被丟棄了,這時出現了問題。
普通版:
class singleton
_mtx.unlock();//解鎖
return _inst;
} void print()
private:
singleton()
:_a(0)
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
int _a;
static singleton* _inst;
static mutex _mtx; //只有乙個鎖
};mutex singleton::_mtx ;//呼叫mutex的建構函式
singleton* singleton:: _inst = null;
上面所實現的單例類,存在一定的缺陷。如果在鎖之間的**出現異常時,便會導致沒有解鎖,導致大量的執行緒阻塞在_mtx.lock() 處,進而可能會出現死鎖。出現死鎖便是很危險的事情。可以對鎖資源,利用raii思想來解決此問題。
raii:資源獲得即初始化,資源在建構函式時初始化,自動呼叫析構函式,釋放資源。
class lock()
~lock()
private:
mutex& _mtx; //保證只有一把鎖
}
優化版:class singleton
return _inst;
} void print()
private:
singleton()
:_a(0)
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
int _a;
static singleton* _inst;
static mutex _mtx;
};mutex singleton::_mtx ;
singleton* singleton:: _inst = null;
注意:
1.此處可以自己通過raii思想實現乙個鎖,在c++11中提供了lock_guard類,也可以實現自動釋放
方法三、考慮安全和效率
方法二雖然解決了執行緒安全,但並不高效。
高效版:
class singleton
} return _inst;
} void print()
private:
singleton()
:_a(0)
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
int _a;
static singleton* _inst;
static mutex _mtx; //只有乙個鎖
};mutex singleton::_mtx ; //呼叫mutex的建構函式
singleton* singleton:: _inst = null;
單例模式分類:
由分類可知:上面的單列模式都屬於懶漢模式。
餓漢模式:
class singleton
void print()
private:
singleton()
:_a(0)
singleton(const singleton&);
singleton& operator=(const singleton&);
static singleton* _inst = new singleton;
private:
int _a;
static mutex _mtx;
};mutex singleton::_mtx ;
比較:
懶漢模式:相對複雜,但在各種場景下都使用;
餓漢模式:簡結,但適用性有限制 例如:動態庫:只有在執行時才載入
C 單例模式
include using namespace std 單例類的c 實現 class singleton 構造方法實現 singleton singleton void singleton setvar int var main int main int argc,char argv return ...
C 單例模式
實現方式一 include template typename t class singleton boost noncopyable static void init private static pthread once t ponce statict value template typena...
C 單例模式
效率有點低,但是還算安全的單例模式,靜態成員實現方式 class singleton public static singleton getinstance singleton singleton getinstance unlock return m instance 內部靜態例項的懶漢模式,c ...