C++設計模式之八--Builder建造者模式

轉自:http://www.cnblogs.com/jiese/p/3161076.html


作用:
將一個複雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

Builder模式和AbstractFactory模式在功能上很相似,因爲都是用來創建大的複雜的對象,它們的區別是:Builder模式強調的是一步步創建對象,並通過相同的創建過程可以獲得不同的結果對象,一般來說Builder模式中對象不是直接返回的。而在AbstractFactory模式中對象是直接返回的,AbstractFactory模式強調的是爲創建多個相互依賴的對象提供一個同一的接口。

適用於以下情況:

1)當創建複雜對象的算法應該獨立於該對象的組成部分以及它們的裝配方式時。

2)當構造過程必須允許被構造的對象有不同的表示時。

UML圖如下

Builder:定義創建對象過程的抽象,提供構建不同組成部分的接口

其中:BuildPartA,BuildPartB,BuildPartC是對一個對象不同部分的構建函數接口,由Builder的派生類ConcreteBuilder1、ConcreteBuilder2來具體實現.
另外還有一個需要注意的函數,就是Director::Construct函數,這個函數裏面通過調用上面的接口函數完成對象的構建--也就是說各個不同部分裝配的過程都是一致的(同樣的調用的Construct函數),但是不同的構建方式會有不同的表示(根據Builder的實際類型來決定如何構建,也就是多態)

Builder模式是基於這樣的一個情況:一個對象可能有不同的組成部分,這幾個部分的不同的創建對象會有不同的表示,但是各個部分之間裝配的方式是一致的.比方說一輛單車,都是由車輪車座等等的構成的(一個對象不同的組成部分),不同的品牌生產出來的也不一樣(不同的構建方式).雖然不同的品牌構建出來的單車不同,但是構建的過程還是一樣的

也就是說,Director::Construct函數中固定了各個組成部分的裝配方式,而具體是裝配怎樣的組成部分由Builder的派生類實現.

實現:
Builder模式的實現基於以下幾個面向對象的設計原則:

1)把變化的部分提取出來形成一個基類和對應的接口函數,在這裏不會變化的是都會創建PartA和PartB,變化的則是不同的創建方法,於是就抽取出這裏的Builder基類和BuildPartA,BuildPartB接口函數

2)採用聚合的方式聚合了會發生變化的基類,就是這裏Director聚合了Builder類的指針.

以上,通過兩個派生類ConcreteBuilder1、ConcreteBuilder2定義了兩種不同的建造細節(建造步驟是一樣的,由Construct函數確定),通過兩個派生類所建造出來的對象,對外部所展現出來的屬性或者功能是不一樣的,由各自Builder派生類中的建造方法(BuildPartA、BuildPartB、BuildPartC)決定。

代碼如下:

Builder.h

複製代碼
 1 #ifndef _BUILDER_H_
 2 #define _BUILDER_H_
 3 
 4 #include <string>
 5 #include <vector>
 6 
 7 using namespace std;
 8 
 9 //產品類
10 class Product
11 {
12 private:
13     string m_partA;
14     string m_partB;
15     string m_partC;
16 public:
17     void setPartA(const string& s);
18     void setPartB(const string& s);
19     void setPartC(const string& s);
20     Product();
21     ~Product();
22 };
23 
24 //抽象Builder基類,定義不同部分的創建接口
25 class Builder
26 {
27 public:
28     virtual void BuildPartA()=0;
29     virtual void BuildPartB()=0;
30     virtual void BuildPartC()=0;
31     virtual Product* GetProduct()=0;
32     Builder();
33     virtual ~Builder();
34 };
35 
36 //  Builder的派生類,實現BuilderPartA和BuilderPartB和BuildPartC接口函數 
37 class ConcreteBuilder1:public Builder
38 {
39 public:
40     ConcreteBuilder1();
41     ~ConcreteBuilder1();
42     virtual void BuildPartA();
43     virtual void BuildPartB();
44     virtual void BuildPartC();
45     virtual Product* GetProduct();
46 private:
47     Product* m_pProduct;
48 };
49 
50 //  Builder的派生類,實現BuilderPartA和BuilderPartB和BuildPartC接口函數 
51 class ConcreteBuilder2:public Builder
52 {
53 public:
54     ConcreteBuilder2();
55     ~ConcreteBuilder2();
56     virtual void BuildPartA();
57     virtual void BuildPartB();
58     virtual void BuildPartC();
59     virtual Product* GetProduct();
60 private:
61     Product* m_pProduct;
62 };
63 
64 //ConcreteBuilder1與ConcreteBuilder2是Builder的兩個派生類,用於實現兩種不同的建造細節
65 
66  // 使用Builder構建產品,構建產品的過程都一致,但是不同的builder有不同的實現
67  // 這個不同的實現通過不同的Builder派生類來實現,存有一個Builder的指針,通過這個來實現多態調用 
68 class Director
69 {
70 public:
71     Director(Builder* pBuilder);
72     ~Director();
73 
74     //Construct函數定義一個對象的整個構建過程,不同的部分之間的裝配方式都是一致的,
75     //首先構建PartA其次是PartB,只是根據不同的構建者會有不同的表示 
76     void Construct();
77     //void Construct(const string& buildPara);
78 private:
79     Builder* m_pBuilder;
80 };
81 
82 #endif
複製代碼

Director.cpp

複製代碼
  1 #include "Builder.h"
  2 #include <iostream>
  3 #include <vector>
  4 
  5 using namespace std;
  6 
  7 Product::~Product()
  8 {
  9 }
 10 
 11 Product::Product()
 12 {}
 13 
 14 void Product::setPartA(const string& s)
 15 {
 16     this->m_partA = s;
 17 }
 18 
 19 void Product::setPartB(const string& s)
 20 {
 21     this->m_partB = s;
 22 }
 23 
 24 void Product::setPartC(const string& s)
 25 {
 26     this->m_partC = s;
 27 }
 28 
 29 Builder::Builder()
 30 {}
 31 
 32 Builder::~Builder()
 33 {}
 34 
 35 ConcreteBuilder1::ConcreteBuilder1()
 36 {
 37     this->m_pProduct = new Product();
 38     cout<<"Create empty product!"<<endl;
 39 }
 40 
 41 void ConcreteBuilder1::BuildPartA()
 42 {
 43     this->m_pProduct->setPartA("A");
 44     cout<<"BuildPartA"<<endl;
 45 }
 46 
 47 void ConcreteBuilder1::BuildPartB()
 48 {
 49     this->m_pProduct->setPartB("B");
 50     cout<<"BuildPartB"<<endl;
 51 }
 52 
 53 void ConcreteBuilder1::BuildPartC()
 54 {
 55     this->m_pProduct->setPartC("C");
 56     cout<<"BuildPartC"<<endl;
 57 }
 58 
 59 Product* ConcreteBuilder1::GetProduct()
 60 {
 61     return this->m_pProduct;
 62 }
 63 
 64 ConcreteBuilder1::~ConcreteBuilder1()
 65 {
 66     delete this->m_pProduct;
 67     this->m_pProduct = NULL;
 68 }
 69 
 70 ConcreteBuilder2::ConcreteBuilder2()
 71 {
 72     this->m_pProduct = new Product();
 73     cout<<"Create empty product!"<<endl;
 74 }
 75 
 76 void ConcreteBuilder2::BuildPartA()
 77 {
 78     this->m_pProduct->setPartA("A");
 79     cout<<"BuildPartA"<<endl;
 80 }
 81 
 82 void ConcreteBuilder2::BuildPartB()
 83 {
 84     this->m_pProduct->setPartB("B");
 85     cout<<"BuildPartB"<<endl;
 86 }
 87 
 88 void ConcreteBuilder2::BuildPartC()
 89 {
 90     this->m_pProduct->setPartC("C");
 91     cout<<"BuildPartC"<<endl;
 92 }
 93 
 94 Product* ConcreteBuilder2::GetProduct()
 95 {
 96     return this->m_pProduct;
 97 }
 98 
 99 ConcreteBuilder2::~ConcreteBuilder2()
100 {
101     delete this->m_pProduct;
102     this->m_pProduct = NULL;
103 }
104 
105 Director::Director(Builder* pBuilder)
106 {
107     this->m_pBuilder = pBuilder;
108 }
109 
110 void Director::Construct()
111 {
112     this->m_pBuilder->BuildPartA();
113     this->m_pBuilder->BuildPartB();
114     this->m_pBuilder->BuildPartC();
115 }
116 
117 Director::~Director()
118 {
119     delete this->m_pBuilder;
120     this->m_pBuilder = NULL;
121 }
複製代碼

main.cpp

複製代碼
 1 #include "Builder.h"
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     Director* pDirector = new Director(new ConcreteBuilder1());
 9     pDirector->Construct();
10 
11     Director* pDirector1 = new Director(new ConcreteBuilder2());
12     pDirector1->Construct();
13 
14     return 0;
15 }
複製代碼

 

建造者模式和工廠模式非常相似呀,但是記住一點你就可以遊刃有餘的使用了:

建造者模式最主要功能是基本方法的調用順序安排,也就是這些基本方法已經實現了;

而工廠方法則重點是創建,你要什麼對象我創造一個對象出來,組裝順序則不是他關心的。

建造者模式使用的場景,一是產品類非常的複雜,或者產品類中的調用順序不同產生了不同的效能,這個時候使用建造者模式是非常合適


發佈了139 篇原創文章 · 獲贊 11 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章