對(duì)象性能模式
十四。單例模式
關(guān)鍵點(diǎn):只存在一個(gè)實(shí)例(以保證邏輯上的正確性)
創(chuàng)建型的設(shè)計(jì)模式繞過new是為了避免new帶來的耦合
這個(gè)繞過new解決的是性能問題
問題:以上寫法單線程是安全的魂莫;而線程則不安全
解決:加鎖(但鎖的代價(jià)過高)
Singleton*Singleton::getInstance(){
?Lock lock;
if(m_instance == nullptr{
?? m_instance= new Singleton();
}
return m_instance;
}
問題:對(duì)于都是讀操作的線程是浪費(fèi)的(即讀操作是安全的)(高并發(fā)環(huán)境下會(huì)有許多讀操作)
解決:雙檢查鎖(鎖前鎖后都要檢查)
Singleton* Singleton::getInstance(){
?? if(m_instance==nullptr){
???????? Lock lock;
????? if(m_instance == nullptr{
????????? m_instance = new???Singleton();
???? ?}
?? }
}
鎖前檢查:避免代價(jià)過高
鎖后檢查:避免不正確
問題(2000年左右再java領(lǐng)域發(fā)現(xiàn)):會(huì)出現(xiàn)reorder的情況導(dǎo)致雙檢查鎖的失效
reorder:實(shí)際上代碼到了指令層次;指令和假設(shè)不一樣遍愿;
m_instance = new Singleton();這一行有幾個(gè)假設(shè);如果拆分成三個(gè)步驟的話:1.分配內(nèi)存2.調(diào)用構(gòu)造器3.把指針得到的返回值給m_instance
以上是假想順序:實(shí)際上有可能reorder(即先分配內(nèi)存耘斩,再把內(nèi)存地址給m_instance最后再調(diào)用構(gòu)造器)沼填;
c++加了一個(gè)關(guān)鍵字(volatile)以解決上述問題;
模式定義:保證一個(gè)類僅有一個(gè)實(shí)例括授,并提供一個(gè)該實(shí)例的全局訪問點(diǎn)
要點(diǎn)總結(jié):
1.實(shí)例構(gòu)造器可以設(shè)置為protected以允許子類派生
2.一般不要支持拷貝構(gòu)造函數(shù)和clone接口坞笙,因?yàn)檫@有可能導(dǎo)致多個(gè)對(duì)象實(shí)例,與初衷違背
3.雙檢查鎖的正確實(shí)現(xiàn)可以實(shí)現(xiàn)多線程環(huán)境下的安全Singleton
注:nullptr荚虚?薛夜??
行為變化模式
組件的構(gòu)件過程中版述,組件行為的變化經(jīng)常導(dǎo)致組建本身劇烈的變化梯澜。“行為變化模式”將組件的行為和組件本身進(jìn)行解耦渴析,從而支持組件行為的變化腊徙,實(shí)現(xiàn)兩者之間的送耦合
非虛和靜態(tài)函數(shù):地址直接以編譯時(shí)綁定方式
虛函數(shù):運(yùn)行時(shí)綁定
二一简十。命令模式
動(dòng)機(jī)1.行為請(qǐng)求者與行為是閑著通常呈現(xiàn)一種緊耦合。但在某些場(chǎng)合——比如需要對(duì)香味進(jìn)行“記錄撬腾、撤銷/重、事物”等處理恢恼,這種無法抵御變化的緊耦合是不合適的民傻。2.這種情況下,如何將“行為請(qǐng)求者”與行為實(shí)現(xiàn)者“解耦场斑?將一組行為抽象為對(duì)象漓踢,可以實(shí)現(xiàn)二者之間的松耦合