在GOF的《設計模式 可復用面向?qū)ο筌浖幕A》中是這樣說的:將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創(chuàng)建不同的表示乍恐。
這句話评疗,似懂非懂的。一個復雜對象的創(chuàng)建茵烈,其通常是由很多的子對象構成百匆;如果一個對象能夠直接就創(chuàng)建好了,那么也不會稱之為復雜對象呜投。由于項目中需求的變化加匈,這個復雜對象的各個部分經(jīng)常會發(fā)生劇烈的變化,但是仑荐,不管怎么變化雕拼,將它們組合在一起,組成一個復雜的對象的事實是不會變的粘招。建造者模式就提供了一種“封裝機制”來將各個對象的變化隔離開啥寇,最終,組合成復雜對象的過程是不會變的洒扎。
這也體現(xiàn)了設計模式的一個很重要的思想就是 :封裝不變的部分辑甜,隔離變化的部分。
在《大話設計模式》一書中袍冷,例舉了一個很好的例子————建造小人磷醋。建造一個小人,要分為六步:頭部胡诗、身體邓线、左手、右手煌恢、左腳和右腳骇陈。與抽象工廠模式不同的是,建造者模式是在Director的控制下一步一步的構造出來的症虑,在建造的過程中缩歪,建造者模式可以進行更精細的控制。不管人的頭部谍憔、身體、左手主籍、右手习贫、左腳或者右腳如何變化,但是最終還是由這幾部分組合在一起形成一個人千元,雖然是同一個建造過程苫昌,但是這個人就會有不同的表示,比如幸海,胖子祟身,瘦子奥务,個高的,個低的等等袜硫。
#include <iostream>
using namespace std;
enum ManType
{
Fatman,
Thinman,
Normalman
};
class Man{
private:
ManType m_type;
public:
void SetHead(ManType type) { m_type = type; }
void SetBody(ManType type) { m_type = type; }
void ShowMan() {
switch (m_type) {
case Fatman:
cout << "fat man" << endl;
break;
case Thinman:
cout << "fat man" << endl;
break;
case Normalman:
cout << "normal man" << endl;
default:
return;
}
return;
}
};
class Build {
public:
virtual void BuildHead(){}
virtual void BuildBody(){}
virtual Man * GetMan() { return NULL; }
};
class FatMenBuild :public Build {
private:
Man * m_FatMan;
public:
FatMenBuild() {m_FatMan = new Man();}
void BuildHead(){
m_FatMan->SetHead(Fatman);
}
void BuildBody() {
m_FatMan->SetBody(Fatman);
}
Man * GetMan() { return m_FatMan; }
};
class ThinMenBuild :public Build {
private:
Man * m_thinMan;
public:
ThinMenBuild() { m_thinMan = new Man(); }
void BuildHead() {
m_thinMan->SetHead(Thinman);
}
void BuildBody() {
m_thinMan->SetBody(Thinman);
}
Man * GetMan() { return m_thinMan; }
};
class Director {
public:
Director(Build * Builder) { m_Builder = Builder; }
void CreateMan() {
m_Builder->BuildHead();
m_Builder->BuildHead();
}
private:
Build * m_Builder;
};
int main() {
//step 1:
Build * buildobj = new FatMenBuild();
//step 2:
Director directorobj(buildobj);
//step 3:
directorobj.CreateMan();
//step 4:
Man * manobj = buildobj->GetMan();
if (manobj == NULL) {
return 0;
}
manobj->ShowMan();
delete manobj;
manobj = NULL;
delete buildobj;
buildobj = NULL;
system("pause");
return 0;
}
使用要點 :
<ul>
<li>建造者模式生成的對象有復雜的內(nèi)部結構氯葬,將分步驟的去構建一個復雜的對象,分多少步是確定的婉陷,而每一步的實現(xiàn)是不同的帚称,可能經(jīng)常發(fā)生變化;</li>
<li>在上面的例子中秽澳,我們都看到了最終生成的Man和Product都沒有抽象類闯睹,這又導出建造者適用的一種情況,當需要創(chuàng)建復雜對象的過程中担神,復雜對象沒有多少共同的特點楼吃,很難抽象出來時,而復雜對象的組裝又有一定的相似點時妄讯,建造者模式就可以發(fā)揮出作用所刀。簡單的說,可能使用了建造者模式捞挥,最終建造的對象可能沒有多大的關系浮创,關于這一點,閱讀《設計模式 可復用面向?qū)ο筌浖幕A》中的建造者模式時是最有體會的砌函。</li>
</ul>
小結:
一個復雜對象是由多個部件組成的斩披,建造者模式是把復雜對象的創(chuàng)建和部件的創(chuàng)建分別開來,分別用Builder類和Director類來表示讹俊。用Director構建最后的復雜對象垦沉,而在上面Builder接口中封裝的是如何創(chuàng)建一個個部件(復雜對象是由這些部件組成的),也就是說仍劈,Director負責如何將部件最后組裝成產(chǎn)品厕倍。這樣建造者模式就讓設計和實現(xiàn)解耦了。