對於當前不知道或無法確定的東西,我們就抽象它,只對其介面操作,即現在不知道具體的涉及物件,但我知道如何使用它,先用其介面,待以後知道了具體的物件之後,再繫結上即可,這就是所謂的封裝變化。
雖然不確定目標是誰,但可以確定如何使用目標。
多種多樣的設計模式其實做的就是 封裝變化 ,面對不同的情景,分析什麼是變化的,什麼是不變的,封裝變化,使上層**能夠「以不變應萬變」。
【嚴格來說其並不算是一種設計模式,其就是把一堆判斷建立的語句放在了乙個函式中,通過傳入的引數決定建立哪乙個產品的例項】
在簡單工廠模式中,可以根據引數的不同返回不同類的例項。簡單工廠模式專門定義乙個類來負責建立其他類的例項,被建立的例項通常都具有共同的父類。(這也是其優點:把實現物件的建立和物件的使用分離)
在實際開發中,還可以在呼叫時將所傳入的引數儲存在xml等格式的配置檔案中,修改引數時無須修改任何源**。
工廠類將全部建立邏輯集中到了乙個工廠類中;它所能建立的類只能是事先考慮到的,如果需要新增新的類,則就需要改變工廠類了。
class factory}};
由於簡單工廠很容易違反高內聚責任分配原則,因此一般只在很簡單的情況下應用。
【產品主體延遲到子類決定,產品的操作由基類實現,子類只負責具體建立某產品】
(變化的是產品,不變的是對產品的操作)
由於簡單工廠模式的侷限性,比如:工廠現在能生產producta、productb和productc三種產品了,此時,需要增加生產productd產品;那麼,首先是不是需要在產品列舉型別中新增新的產品型別標識,然後,修改factory類中的switch結構**。這種對**的修改量較大,易產生編碼上的錯誤。
工廠方法模式是簡單工廠模式的進一步抽象和推廣。由於使用了物件導向的多型性,工廠方法模式保持了簡單工廠模式的優點,而且克服了它的缺點。
在工廠方法模式中,核心的工廠類不再負責所有產品的建立,而是將具體建立工作交給子類去做。這個核心類僅僅負責給出具體工廠必須實現的介面,而不負責哪乙個產品類被例項化這種細節,這使得工廠方法模式可以允許系統在不修改工廠角色的情況下引進新產品。
相似的產品有相同的操作,我們對產品的介面操作,讓產品的生成延遲到子類。(這些操作是固定的,但操作的目標是變化的)
不同的子類生產不同的產品,你選擇了哪種子類,就相當於你選擇了哪種產品。
簡單示例**:
class factory
;class factorya : public factory
};class factoryb : public factory
};//對產品的操作,這些產品有共同的介面
void factory::operateproduct()
int main(void)
1、這和我們直接new乙個產品物件有什麼區別?
product* product = new productb() ;
product->show() ;
product->change() ;
區別是我們的工廠類中有圍繞著產品進行的對產品的操作。我們使用這個操作框架(我們保證這個操作框架是基本不變的)。我們直接對產品進行操作而不通過工廠類,則相同的對產品的操作**會散落在各處,**重用性不好。
我們就是在乙個框架中使用工廠方法的,框架使用抽象類定義物件之間的關係,這些物件的建立通常也由框架負責。(我們就是為了**重用才使用框架的,不會說是直接使用產品類,在客戶**中再重寫這些與產品相關的框架**)
【類似模板方法】
工廠方法通常在模板方法中被呼叫。
2、使用模板以避免建立子類
從上面的例子看到,在使用工廠方法時,我們要new乙個相應的工廠類,然後在使用完畢後需要delete它。這樣做比較繁瑣。
解決方式:我們可以把new的工廠類放入auto_ptr智慧型指標類,由智慧型指標負責管理我們動態分配的物件。
或者,把工廠類設計成模板類
即:
template product* stdfactory : public factory
}使用這個模板,我們就不需要再new工廠的子類了
stdfactoryfactoryb ;
【把一系列相關的元件,放在乙個工廠建立,這樣只需換乙個工廠,就可以換乙個產品系列】
(變化的是產品的形態種類,不變的是對產品的操作集)
抽象工廠是諸多設計模式中最為「巨集偉」的乙個模式。(這裡說的巨集偉,意為更換乙個抽象工廠,對系統的面貌影響較大)
可以用「一橫一豎」來概括抽象工廠。
當你要強調一系列相關的產品物件的設計以便進行聯合使用時。
【在很多軟體系統中需要更換介面主題,要求介面中的按鈕、文字框、背景色等一起發生改變時,可以使用抽象工廠模式進行設計。】
乙個抽象工廠建立了乙個完整的產品系列。
抽象工廠只負責建立這些種類的產品,而不負責組裝這些產品為成品。
【將乙個物件的構建與它的表示分離,使得同樣的構建過程可以建立不同的表示】
(變化的是零件,不變的是對這些零件的組裝過程)
這樣的話,我們可以方便地改變產品的內部表示,即可以方便地更換零件,產品的總結構不變。
示例**
int main(void)
product* director::constuct()
【就是,當需要建立由許多零件裝配的物件時,使用建造者模式】
【在很多遊戲軟體中,地圖包括天空、地面、背景等組成部分,人物角色包括人體、服裝、裝備等組成部分,可以使用建造者模式對其進行設計,通過不同的具體建造者建立不同型別的地圖或人物。】
builder類與抽象工廠類十分相似,但抽象工廠建立的是一系列有關的產品,建造者模式建立的是一系列有關的零件,最後還需要導演類來組裝零件成產品。(多了乙個導演類來組裝零件,兩者的關注點不同)
注意:導演只是對組裝過程進行引導,最終還是builder組裝並產出產品。(導演類中是包含建造者的,所有建立工作由建造者負責完成)導演呼叫builder一步一步把零件填裝到其空骨架中,最終返回乙個成品。
如果將抽象工廠模式看成 汽車配件生產工廠 ,生產乙個產品族的產品,那麼建造者模式就是乙個 汽車組裝工廠 ,通過對部件的組裝可以返回一輛完整的汽車。
將工廠模式稍加變化可以得到建造者(builder)模式。工場模式的「加工工藝」是隱藏的,而建造模式的「加工工藝」是暴露的。把工廠方法的乙個方法分成做個方法步驟去構造乙個產品,即為建造者模式。
【用static函式返回此單件的指標】
懶漢式
懶漢式的特點是延遲載入,比如配置檔案的單例,採用懶漢式的方法,顧名思義,懶漢麼,很懶的,配置檔案的例項直到用到的時候才會載入。
class singleton
;//實現
singleton* singleton::_instance = 0 ;
singleton* singleton::instance()
return _instance ;
}
這種簡單的懶漢式單例,new出來的東西始終沒有釋放,雖然只有乙份,不太可能造成記憶體洩露。
但我們可以在單例類中新增乙個靜態物件專門用來釋放new出來的單例。
改進版懶漢:
class singleton
protected:
csingleton()
private:
static singleton *_instance;
class cfreeinstance
};
static cfreeinstance afree;
};
餓漢式:懶漢式單例有執行緒安全問題,在if判斷_instance是否為null時,多執行緒訪問會出現安全問題。
餓漢式的特點是一開始就載入了,餓漢式是執行緒安全的,在類建立的同時就已經建立好乙個靜態的物件供系統使用,以後不再改變。
class singleton
public:
static singleton * getinstance()
};
【參考】
《設計模式之禪》
《gof設計模式》
設計模式的一點思考
建立型 builder 當我們要建立的物件很複雜的時候 通常是由很多其他的物件組合而成 我們要將複雜物件的建立過程和這個物件的表示 展示 分離開來,這樣做的好處就是通過一步一步的進行複雜物件的構建,由於在每一步的構造過程中可以引入引數,使得同樣的構建過程可以建立不同的表示。abstractfacto...
網路協議設計的一點思考
分層協議一般都提供一種或幾種固定的服務,這些服務中高層一些的大多數都是通過 握手 動作來協商的,另外一些比較底層的服務則是協議本身提供的,比如udp服務,ip服務等。下層的握手過程對上層不可見,握手其實就是協商一條帶有一定功能 可以提供一定服務 的虛擬鏈路,握手完成之後,下層也就承諾了那種服務,之後...
網路協議設計的一點思考
分層協議一般都提供一種或幾種固定的服務,這些服務中高層一些的大多數都是通過 握手 動作來協商的,另外一些比較底層的服務則是協議本身提供的,比如udp服務,ip服務等。下層的握手過程對上層不可見,握手其實就是協商一條帶有一定功能 可以提供一定服務 的虛擬鏈路,握手完成之後,下層也就承諾了那種服務,之後...