詳解C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn)
建造者模式:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。這是建造者模式的標(biāo)準(zhǔn)表達(dá),不過看著讓人迷惑,什么叫構(gòu)建和表示的分離?一個(gè)對(duì)象使用構(gòu)造函數(shù)構(gòu)造之后不就固定了,只有通過它方法來改變它的屬性嗎?而且還要同樣的構(gòu)建過程搞出不同的表示,怎么可能呢?多寫幾個(gè)構(gòu)造函數(shù)?
其實(shí)多寫幾個(gè)構(gòu)造函數(shù),根據(jù)不同參數(shù)設(shè)置對(duì)象不同的屬性,也可以達(dá)到這樣的效果,只是這樣就非常麻煩了,每次要增加一種表示就要添加一個(gè)構(gòu)造函數(shù),將來構(gòu)造函數(shù)會(huì)多得連自己都不記得了,這違背了開放-封閉的原則。
要不就只能設(shè)計(jì)幾個(gè)set函數(shù),每次屬性不一樣了,我就構(gòu)造一個(gè)對(duì)象,然后用set函數(shù)改變對(duì)象的屬性。這樣也可以達(dá)到效果。只是代碼就會(huì)非常冗余了,每個(gè)要用到這個(gè)對(duì)象的地方,都要寫上好幾句語句,一旦對(duì)象有點(diǎn)什么變化,還得到處都改一遍,這樣就很容易出錯(cuò),以后別人看著這種神邏輯和神代碼估計(jì)也會(huì)崩潰了。而且這也違背了依賴倒轉(zhuǎn)的原則。
于是大神們就開始想了,不能加很多構(gòu)造函數(shù),也不能直接用一堆set函數(shù),然后發(fā)現(xiàn),有些對(duì)象的構(gòu)建是固定的幾個(gè)步驟的,就像一條流水線一樣,任何的產(chǎn)品都是通過每一個(gè)固定的步驟拼湊出來的。例如說一部手機(jī),先放主板,再放屏幕,再放電池,再放外殼,貼個(gè)膜就能賣幾千了,每次推出新產(chǎn)品,就換個(gè)更好的主板,換個(gè)大點(diǎn)的屏幕,再整個(gè)大容量電池,貼個(gè)超牛B的高透膜,又能賣出個(gè)新價(jià)錢。就是說,這些步驟都沒有變,變的只是每個(gè)部分的東西。
這就是大神的厲害之處了,透過現(xiàn)象看本質(zhì),基本有變的,有不變的,那敢情好,面向?qū)ο蟮囊粋€(gè)重要指導(dǎo)思想就是,封裝隔離變化的,留出不變的。于是他們就用一個(gè)Builder類把步驟中的每個(gè)部分封裝起來,這個(gè)類的主要作用就是生產(chǎn)每個(gè)部件,再抽象一下提升高度,這樣就依賴倒轉(zhuǎn)了,這樣每次只需要添加一個(gè)類,這個(gè)類還是這幾個(gè)部分,只是內(nèi)部的實(shí)現(xiàn)已經(jīng)不一樣了,這樣就滿足了開放-封閉的原則了。但還是有一個(gè)問題,光有Builder類還不行,雖然產(chǎn)品的每個(gè)部分都有對(duì)應(yīng)的函數(shù),但是用起來的話,還是跟前面說的set函數(shù)一樣,一用就要使用一大堆函數(shù),也就是這變的東西是封裝起來了,但這不變的東西還沒留出來。這時(shí),就添加一個(gè)Director類,這個(gè)類就是專門規(guī)定組裝產(chǎn)品的步驟的,這樣只要告訴Director使用哪個(gè)Builder,就能生產(chǎn)出不同的產(chǎn)品,對(duì)于客戶端來說,只看到用了Director的一個(gè)construct函數(shù),甚是方便。
再反過來看建造者模式的定義,構(gòu)建指的就是生產(chǎn)一個(gè)產(chǎn)品的步驟,表示就是每個(gè)產(chǎn)品部分的具體實(shí)現(xiàn),通過Director封裝步驟,通過Builder封裝產(chǎn)品部分的實(shí)現(xiàn),再把他兩隔離開,就能隔離變的,留出不變的供客戶端使用。
圖中可以看到,Product是必須要知道,沒有抽象,但是這個(gè)產(chǎn)品卻可以由不同的部分組合而成。Director里的construct也是固定,沒有抽象出來,如果要更改步驟,也要添加一個(gè)函數(shù),或者再添一個(gè)Diector,所以建造者模式一般應(yīng)用于步驟不會(huì)發(fā)生大的變化,而產(chǎn)品會(huì)發(fā)生大變化的情況。
常用的場(chǎng)景
C#中的StringBuilder就是一個(gè)建造者的例子,但只是一個(gè)建造者,還缺一個(gè)Director,不能算一個(gè)完整的建造者模式。建造者模式一般應(yīng)用于構(gòu)建產(chǎn)品的步驟(也可以稱為算法)不變,而每個(gè)步驟的具體實(shí)現(xiàn)又劇烈變化的情況。
優(yōu)點(diǎn)
1.隔離了構(gòu)建的步驟和具體的實(shí)現(xiàn),為產(chǎn)品的具體實(shí)現(xiàn)提供了靈活度。
2.封裝和抽象了每個(gè)步驟的實(shí)現(xiàn),實(shí)現(xiàn)了依賴倒轉(zhuǎn)原則。
3.封裝了具體的步驟,減少了代碼的冗余。
缺點(diǎn)
1.要求構(gòu)建產(chǎn)品的步驟(算法)是不能劇烈變化的,最好是不變的,這樣就影響了靈活度。
實(shí)例
#include "stdafx.h" #include <stdlib.h> #include <iostream> using namespace std; //抽象類,用來安排創(chuàng)建人的具體流程,其他類必須遵循這個(gè)流程,但是可以自己具體實(shí)現(xiàn) class CPersonBuilder { public: virtual void BuildHead()=0; virtual void BuildBody()=0; virtual void BuildArmLeft()=0; virtual void BuildArmRight()=0; virtual void BuildLegLeft()=0; virtual void BuildLegRight()=0; }; //創(chuàng)建瘦子的類 class CThinPersonBuilder:public CPersonBuilder { public: CThinPersonBuilder() { cout<<"is creating thin person "<<endl<<endl; } ~CThinPersonBuilder() { cout<<"is finished for thin person"<<endl<<endl; } public: void BuildHead() { cout<<"BuildHead"<<endl; } void BuildBody() { cout<<"BuildBody(thin)"<<endl; } void BuildArmLeft() { cout<<"BuildArmLeft"<<endl; } void BuildArmRight() { cout<<"BuildArmRight"<<endl; } void BuildLegLeft() { cout<<"BuildLegLeft"<<endl; } void BuildLegRight() { cout<<"BuildLegRight"<<endl; } }; //創(chuàng)建胖子的類 class CFatPersonBuilder:public CPersonBuilder { public: CFatPersonBuilder() { cout<<"is creating fat person"<<endl; } ~CFatPersonBuilder() { cout<<"is finished for fat person"<<endl; } public: void BuildHead() { cout<<"BuildHead"<<endl; } void BuildBody() { cout<<"BuildBody(Fat)"<<endl; } void BuildArmLeft() { cout<<"BuildArmLeft"<<endl; } void BuildArmRight() { cout<<"BuildArmRight"<<endl; } void BuildLegLeft() { cout<<"BuildLegLeft"<<endl; } void BuildLegRight() { cout<<"BuildLegRight"<<endl; } }; //指揮者類,用來指揮創(chuàng)建的人是瘦子還是胖子 class CPersonDirector { public: CPersonDirector(CPersonBuilder *p) { this->m_p=p; } const void CreatePerson(void) const { m_p->BuildHead(); m_p->BuildBody(); m_p->BuildArmLeft(); m_p->BuildArmRight(); m_p->BuildLegLeft(); m_p->BuildLegRight(); } private: CPersonBuilder *m_p; }; int _tmain(int argc, _TCHAR* argv[]) { cout<<"---------建造者模式測(cè)試案例------------------------"<<endl<<endl; CThinPersonBuilder *p_tp=new CThinPersonBuilder(); CPersonDirector *p_dtp=new CPersonDirector(p_tp); p_dtp->CreatePerson(); delete p_tp; delete p_dtp; p_tp=NULL; p_dtp=NULL; cout<<endl<<endl; CFatPersonBuilder *p_fp=new CFatPersonBuilder(); CPersonDirector *p_dfp=new CPersonDirector(p_fp); p_dfp->CreatePerson(); delete p_fp; delete p_dfp; p_fp=NULL; p_dfp=NULL; system("pause"); return 0; }
上一篇:詳解C++設(shè)計(jì)模式編程中對(duì)狀態(tài)模式的運(yùn)用
欄 目:C語言
下一篇:C++編程中使用設(shè)計(jì)模式中的policy策略模式的實(shí)例講解
本文標(biāo)題:詳解C++設(shè)計(jì)模式編程中建造者模式的實(shí)現(xiàn)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/2471.html
您可能感興趣的文章
- 04-02c語言沒有round函數(shù) round c語言
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入二叉樹兩個(gè)結(jié)點(diǎn)的最低共同父結(jié)點(diǎn)的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)- 解析最少換車次數(shù)的問題詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)-用棧實(shí)現(xiàn)表達(dá)式求值的方法詳解
- 01-10HDOJ 1443 約瑟夫環(huán)的最新應(yīng)用分析詳解
- 01-10深入理解C++中常見的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10如何查看進(jìn)程實(shí)際的內(nèi)存占用情況詳解
- 01-10深入Main函數(shù)中的參數(shù)argc,argv的使用詳解


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置