作用:
將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。
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 }
建造者模式和工廠模式非常相似呀,但是記住一點你就可以游刃有余的使用了:
建造者模式最主要功能是基本方法的調用順序安排,也就是這些基本方法已經實現了;
而工廠方法則重點是創建,你要什么對象我創造一個對象出來,組裝順序則不是他關心的。
建造者模式使用的場景,一是產品類非常的復雜,或者產品類中的調用順序不同產生了不同的效能,這個時候使用建造者模式是非常合適