C++設計形式之建造者形式。本站提示廣大學習愛好者:(C++設計形式之建造者形式)文章只能為提供參考,不一定能成為您想要的結果。以下是C++設計形式之建造者形式正文
建造者形式
在GOF的《設計形式 可復用面向對象軟件的基本》中是如許說的:將一個龐雜對象的構建與它的表現分別,使得異樣的構建進程可以創立分歧的表現。
這句話,似懂非懂的。一個龐雜對象的創立,其平日是由許多的子對象組成;假如一個對象可以或許直接就創立好了,那末也不會稱之為龐雜對象。因為項目中需求的變更,這個龐雜對象的各個部門常常會產生激烈的變更,然則,不論怎樣變更,將它們組合在一路,構成一個龐雜的對象的現實是不會變的。建造者形式就供給了一種“封裝機制”來將各個對象的變更隔分開,終究,組分解龐雜對象的進程是不會變的。
在《年夜話設計形式》一書中,例舉了一個很好的例子————建造君子。建造一個君子,要分為六步:頭部、身材、左手、右手、左腳和右腳。與籠統工場形式分歧的是,建造者形式是在Director的掌握下一步一步的結構出來的,在建造的進程中,建造者形式可以停止更精致的掌握。不論人的頭部、身材、左手、右手、左腳或許右腳若何變更,然則終究照樣由這幾部門組合在一路構成一小我,固然是統一個建造進程,然則這小我就會有分歧的表現,好比,瘦子,胖子,個高的,個低的等等。
UML圖
類圖以下:
時序圖以下:
代碼完成
/*
** FileName : BuilderPattern
** Author : Jelly Young
** Date : 2013/11/22
** Description : More information, please go to http://www.jb51.net
*/
#include <iostream>
using namespace std;
typedef enum MANTYPETag
{
kFatMan,
kThinMan,
kNormal
}MANTYPE;
class Man
{
public:
void SetHead(MANTYPE type){ m_Type = type; }
void SetBody(MANTYPE type){ m_Type = type; }
void SetLeftHand(MANTYPE type){ m_Type = type; }
void SetRightHand(MANTYPE type){ m_Type = type; }
void SetLeftFoot(MANTYPE type){ m_Type = type; }
void SetRightFoot(MANTYPE type){ m_Type = type; }
void ShowMan()
{
switch (m_Type)
{
case kFatMan:
cout<<"I'm a fat man"<<endl;
return;
case kThinMan:
cout<<"I'm a thin man"<<endl;
return;
default:
cout<<"I'm a normal man"<<endl;
return;
}
}
private:
MANTYPE m_Type;
};
// Builder
class Builder
{
public:
virtual void BuildHead(){}
virtual void BuildBody(){}
virtual void BuildLeftHand(){}
virtual void BuildRightHand(){}
virtual void BuildLeftFoot(){}
virtual void BuildRightFoot(){}
virtual Man *GetMan(){ return NULL; }
};
// FatManBuilder
class FatManBuilder : public Builder
{
public:
FatManBuilder(){ m_FatMan = new Man(); }
void BuildHead(){ m_FatMan->SetHead(kFatMan); }
void BuildBody(){ m_FatMan->SetBody(kFatMan); }
void BuildLeftHand(){ m_FatMan->SetLeftHand(kFatMan); }
void BuildRightHand(){ m_FatMan->SetRightHand(kFatMan); }
void BuildLeftFoot(){ m_FatMan->SetLeftFoot(kFatMan); }
void BuildRightFoot(){ m_FatMan->SetRightFoot(kFatMan); }
Man *GetMan(){ return m_FatMan; }
private:
Man *m_FatMan;
};
// ThisManBuilder
class ThinManBuilder : public Builder
{
public:
ThinManBuilder(){ m_ThinMan = new Man(); }
void BuildHead(){ m_ThinMan->SetHead(kThinMan); }
void BuildBody(){ m_ThinMan->SetBody(kThinMan); }
void BuildLeftHand(){ m_ThinMan->SetLeftHand(kThinMan); }
void BuildRightHand(){ m_ThinMan->SetRightHand(kThinMan); }
void BuildLeftFoot(){ m_ThinMan->SetLeftFoot(kThinMan); }
void BuildRightFoot(){ m_ThinMan->SetRightFoot(kThinMan); }
Man *GetMan(){ return m_ThinMan; }
private:
Man *m_ThinMan;
};
// Director
class Director
{
public:
Director(Builder *builder) { m_Builder = builder; }
void CreateMan();
private:
Builder *m_Builder;
};
void Director::CreateMan()
{
m_Builder->BuildHead();
m_Builder->BuildBody();
m_Builder->BuildLeftHand();
m_Builder->BuildRightHand();
m_Builder->BuildLeftHand();
m_Builder->BuildRightHand();
}
int main(int argc, char *argv[])
{
Builder *builderObj = new FatManBuilder();
Director directorObj(builderObj);
directorObj.CreateMan();
Man *manObj = builderObj->GetMan();
if (manObj == NULL)
return 0;
manObj->ShowMan();
delete builderObj;
builderObj = NULL;
return 0;
};
下面這個例子比擬雜,然則也是建造者形式的運用。上面這個例子是建造者最普通,最簡略的完成辦法:
/*
** FileName : BuilderPattern
** Author : Jelly Young
** Date : 2013/11/23
** Description : More information, please go to http://www.jb51.net
*/
#include <iostream>
#include <vector>
using namespace std;
class Builder;
// Product
class Product
{
public:
void AddPart(const char *info) { m_PartInfoVec.push_back(info); }
void ShowProduct()
{
for (std::vector<const char *>::iterator item = m_PartInfoVec.begin();
item != m_PartInfoVec.end(); ++item)
{
cout<<*item<<endl;
}
}
private:
std::vector<const char *> m_PartInfoVec;
};
// Builder
class Builder
{
public:
virtual void BuildPartA() {}
virtual void BuildPartB() {}
virtual Product *GetProduct() { return NULL; }
};
// ConcreteBuilder
class ConcreteBuilder : public Builder
{
public:
ConcreteBuilder() { m_Product = new Product(); }
void BuildPartA()
{
m_Product->AddPart("PartA completed");
}
void BuildPartB()
{
m_Product->AddPart("PartB completed");
}
Product *GetProduct() { return m_Product; }
private:
Product *m_Product;
};
// Director
class Director
{
public:
Director(Builder *builder) { m_Builder = builder; }
void CreateProduct()
{
m_Builder->BuildPartA();
m_Builder->BuildPartB();
}
private:
Builder *m_Builder;
};
// main
int main()
{
Builder *builderObj = new ConcreteBuilder();
Director directorObj(builderObj);
directorObj.CreateProduct();
Product *productObj = builderObj->GetProduct();
if (productObj == NULL)
{
return 0;
}
productObj->ShowProduct();
delete builderObj;
builderObj = NULL;
}
經由過程比擬下面的兩個例子,可以很輕易的把建造者形式的骨架籠統出來。
應用要點
1.建造者形式生成的對象有龐雜的外部構造,將分步調的去構建一個龐雜的對象,分若干步是肯定的,而每步的完成是分歧的,能夠常常產生變更;
2.在下面的例子中,我們都看到了終究生成的Man和Product都沒有籠統類,這又導出建造者實用的一種情形,當須要創立龐雜對象的進程中,龐雜對象沒有若干配合的特色,很難籠統出來時,而龐雜對象的組裝又有必定的類似點時,建造者形式便可以施展出感化。簡略的說,能夠應用了建造者形式,終究建造的對象能夠沒有多年夜的關系,關於這一點,浏覽《設計形式 可復用面向對象軟件的基本》中的建造者形式時是最有領會的。
總結
一個龐雜對象是由多個部件構成的,建造者形式是把龐雜對象的創立和部件的創立分離開來,分離用Builder類和Director類來表現。用Director構建最初的龐雜對象,而在下面Builder接口中封裝的是若何創立一個個部件(龐雜對象是由這些部件構成的),也就是說,Director擔任若何將部件最初組裝成產物。如許建造者形式就讓設計和完成解耦了。
剛開端接觸建造者形式的時刻,最輕易把建造者和籠統工場形式混雜了。因為而這都屬於創立型的設計形式,所以兩者之間是有公共點的,然則建造者形式重視於對象組合,即分歧的小對象構成一個全體的龐雜年夜對象,而籠統工場形式針關於接口編程,只是對外供給創立對象的工場接口,不擔任對象以後的處置。
建造者形式,是一個比擬龐雜,不輕易衡量的設計形式。年夜家應當更多的浏覽開源代碼,懂得別人是若何應用該形式的。從現實的運用中進修設計形式。