序言
建造者模式,這是一個無法從字面上推測出類圖的模式,但是有了前面的模板方法模式的基礎,在理解建造者模式上,會覺得很簡單。我也盡量多用圖來解釋建造者模式,因為今天在看別人的文章的時候,我發現自己很懶,懶得看那一堆堆的文字。文字固然可以靈巧的組成散文詩歌,但是對於時間倉促,浮躁的程序員來說,如果不是需要這門技術,自己根本沒閑心去看別人的文字。唉,序言有點羅嗦了,估計80%的人都不會完整的看完序言,不過沒關系,看正文就行。
正文
1. 在腦子里形成一個需求圖
稍微解釋一下這個圖,這個圖定義了一個產品的模板,姑且叫產品這個名字吧!其中“執行”這個行為是“操作1”、“操作2”、“操作3”這三個操作的組合,不過,執行順序是不定的,如何構造一個執行序列不一定的方法呢?我們可以靠數組來定義這個執行序列,參考下列代碼:
1 void setSequence(vector<string> quen){ 2 this->sequen = quen; 3 } 4 void execute(){ 5 for(int i = 0; i < sequen.size(); i ++){ 6 if(sequen[i].compare("operator1") == 0){ 7 this->operator1(); 8 }else if(sequen[i].compare("operator2") == 0){ 9 this->operator2(); 10 }else if(sequen[i].compare("operator3") == 0){ 11 this->operator3(); 12 } 13 } 14 }
2. 同一產品系列產品執行序列不同到底是何意?
這是一個擴充的需求圖,不過,我特意標識的紅字部分只有dota玩家能懂。不過沒關系,我來解釋一下,這里我們看到產品系列1和產品系列2中的操作是不同的,但是仍然符合產品模板的規定。其次,兩個產品系列下,都有各自的產品。可以看出,在各個產品中,操作執行序列是不同的。也就是說,操作序列是最后定義的。
現在拋出一個問題,上面的模型該怎么設計呢?由於這節學習的建造者模式,所以,下面我們來一步一步來實現這個建造者模式。
3. 產品模板
產品模板很簡單,定義三個操作和一個執行序列就可以了,但是我們還需要一個可以設置執行序列的數組,這個數組由一個方法來設置。代碼如下:
1 class AbstractProduct{ 2 public: 3 virtual void operator1(){} 4 virtual void operator2(){} 5 virtual void operator3(){} 6 void setSequence(vector<string> quen){ 7 this->sequen = quen; 8 } 9 void execute(){ 10 for(int i = 0; i < sequen.size(); i ++){ 11 if(sequen[i].compare("operator1") == 0){ 12 this->operator1(); 13 }else if(sequen[i].compare("operator2") == 0){ 14 this->operator2(); 15 }else if(sequen[i].compare("operator3") == 0){ 16 this->operator3(); 17 } 18 } 19 } 20 private: 21 vector<string> sequen; 22 };
聰明的小孩會看到,這不就是模板方法模式嗎?把具體實現延遲到子類,父類定義好算法的框架,是的,沒錯,這就是模板方法模式。
2. 產品系列的實現
我們有兩個產品系列,其中都實現了產品模板中沒有實現的三個操作,那么兩個產品系列是如何的呢?代碼如下:
1 class ConcreteProduct1:public AbstractProduct{ 2 void operator1(){ cout<<"Product1: operator1 executing."<<endl; } 3 void operator2(){ cout<<"Product1: operator2 executing."<<endl; } 4 void operator3(){ cout<<"Product1: operator3 executing."<<endl; } 5 }; 6 7 class ConcreteProduct2:public AbstractProduct{ 8 void operator1(){ cout<<"Product2: operator1 executing."<<endl; } 9 void operator2(){ cout<<"Product2: operator2 executing."<<endl; } 10 void operator3(){ cout<<"Product2: operator3 executing."<<endl; } 11 };
3. 具體產品的簡單構建(從這一點可以看出我們需要建造者模式)
現在產品系列出來了,如何建立我們需要的產品呢?一般來說,你肯定會如下這么寫:
1 int main(){ 2 3 AbstractProduct* product = new ConcreteProduct1(); 4 vector<string> sequen; 5 sequen.push_back("operator3"); 6 sequen.push_back("operator2"); 7 sequen.push_back("operator1"); 8 product->setSequence(sequen); 9 product->execute(); 10 11 system("pause"); 12 return 0; 13 }
這樣寫是可以得到我們需要的結果,但是,試想如果我需要很多個不同操作序列的產品,那我這個main里面是不是會很龐大?那該怎么改進呢?
4. 我們需要建造者
建造者長什么樣呢?至少能不用讓我們自己一直new產品吧!代碼參考如下:
1 class ConcreteBuilder1:public AbstractBuilder{ 2 public: 3 AbstractProduct *getProduct(){ 4 return product; 5 } 6 void setSequence(vector<string> quen){ 7 product = new ConcreteProduct1(); 8 product->setSequence(quen); 9 } 10 private: 11 ConcreteProduct1* product; 12 }; 13 14 class ConcreteBuilder2:public AbstractBuilder{ 15 public: 16 AbstractProduct *getProduct(){ 17 return product; 18 } 19 void setSequence(vector<string> quen){ 20 product = new ConcreteProduct2(); 21 product->setSequence(quen); 22 } 23 private: 24 ConcreteProduct2* product; 25 };
上面是兩個產品系列的建造者,這個時候,我們的客戶端調用就變成下面這個樣子了:
1 int main(){ 2 3 AbstractBuilder* builder = new ConcreteBuilder1(); 4 vector<string> sequen; 5 sequen.push_back("operator3"); 6 sequen.push_back("operator2"); 7 sequen.push_back("operator1"); 8 builder->setSequence(sequen); 9 AbstractProduct* product = builder->getProduct(); 10 product->execute(); 11 12 system("pause"); 13 return 0; 14 }
看出來不同沒?我們有Builder了,只要new一個Builder出來,下面我們就不用自己new各個產品了。那么這樣的代碼看起來還是不夠明晰,main里面,即客戶端調用的代碼看起來還是不清爽,這時候我們需要引進一個新類——Director。
5. 隆重登場Director(封裝了各種產品)
它的職責其實就是將上面main里面出現的那一堆代碼封裝起來,然后提供一些方法來構建我們的產品,代碼參考如下:
1 class Director{ 2 public: 3 AbstractProduct* getConcreteProduct1_1_2_3(){ 4 AbstractBuilder* builder = new ConcreteBuilder1(); 5 vector<string> sequen; 6 sequen.push_back("operator1"); 7 sequen.push_back("operator2"); 8 sequen.push_back("operator3"); 9 builder->setSequence(sequen); 10 AbstractProduct* product = builder->getProduct(); 11 return product; 12 } 13 14 AbstractProduct* getConcreteProduct1_3_2_1(){ 15 AbstractBuilder* builder = new ConcreteBuilder1(); 16 vector<string> sequen; 17 sequen.push_back("operator3"); 18 sequen.push_back("operator2"); 19 sequen.push_back("operator1"); 20 builder->setSequence(sequen); 21 AbstractProduct* product = builder->getProduct(); 22 return product; 23 } 24 25 AbstractProduct* getConcreteProduct2_1_2_3(){ 26 AbstractBuilder* builder = new ConcreteBuilder2(); 27 vector<string> sequen; 28 sequen.push_back("operator1"); 29 sequen.push_back("operator2"); 30 sequen.push_back("operator3"); 31 builder->setSequence(sequen); 32 AbstractProduct* product = builder->getProduct(); 33 return product; 34 } 35 36 AbstractProduct* getConcreteProduct2_3_2_1(){ 37 AbstractBuilder* builder = new ConcreteBuilder2(); 38 vector<string> sequen; 39 sequen.push_back("operator3"); 40 sequen.push_back("operator2"); 41 sequen.push_back("operato1"); 42 builder->setSequence(sequen); 43 AbstractProduct* product = builder->getProduct(); 44 return product; 45 } 46 };
6. 新的客戶端調用(變得很簡潔了)
引進了Director后,再來看看我們的客戶端調用吧:
1 int main(){ 2 3 Director* director = new Director(); 4 AbstractProduct* product1 = director->getConcreteProduct1_1_2_3(); 5 product1->execute(); 6 7 AbstractProduct* product2 = director->getConcreteProduct1_3_2_1(); 8 product2->execute(); 9 10 system("pause"); 11 return 0; 12 }
是不是很簡潔了,這就是我們最終的結果!!!
UML圖
我偷懶了,沒有把方法放到里面,注意上面的紅框內的組合,是一個模板方法模式,其他的咱就不多說了,自己研究研究吧!
總結
對於建造者模式的理解還僅限於代碼而已,實際應用場景需要強化,我盡量找機會時間自己的建造者模式,呵呵!
PS:附上最終的完整代碼:
1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 class AbstractProduct{ 6 public: 7 virtual void operator1(){} 8 virtual void operator2(){} 9 virtual void operator3(){} 10 void setSequence(vector<string> quen){ 11 this->sequen = quen; 12 } 13 void execute(){ 14 for(int i = 0; i < sequen.size(); i ++){ 15 if(sequen[i].compare("operator1") == 0){ 16 this->operator1(); 17 }else if(sequen[i].compare("operator2") == 0){ 18 this->operator2(); 19 }else if(sequen[i].compare("operator3") == 0){ 20 this->operator3(); 21 } 22 } 23 } 24 private: 25 vector<string> sequen; 26 }; 27 28 class ConcreteProduct1:public AbstractProduct{ 29 void operator1(){ cout<<"Product1: operator1 executing."<<endl; } 30 void operator2(){ cout<<"Product1: operator2 executing."<<endl; } 31 void operator3(){ cout<<"Product1: operator3 executing."<<endl; } 32 }; 33 34 class ConcreteProduct2:public AbstractProduct{ 35 void operator1(){ cout<<"Product2: operator1 executing."<<endl; } 36 void operator2(){ cout<<"Product2: operator2 executing."<<endl; } 37 void operator3(){ cout<<"Product2: operator3 executing."<<endl; } 38 }; 39 40 class AbstractBuilder{ 41 public: 42 virtual AbstractProduct *getProduct(){ return NULL;} 43 virtual void setSequence(vector<string> quen){} 44 }; 45 46 class ConcreteBuilder1:public AbstractBuilder{ 47 public: 48 AbstractProduct *getProduct(){ 49 return product; 50 } 51 void setSequence(vector<string> quen){ 52 product = new ConcreteProduct1(); 53 product->setSequence(quen); 54 } 55 private: 56 ConcreteProduct1* product; 57 }; 58 59 class ConcreteBuilder2:public AbstractBuilder{ 60 public: 61 AbstractProduct *getProduct(){ 62 return product; 63 } 64 void setSequence(vector<string> quen){ 65 product = new ConcreteProduct2(); 66 product->setSequence(quen); 67 } 68 private: 69 ConcreteProduct2* product; 70 }; 71 72 class Director{ 73 public: 74 AbstractProduct* getConcreteProduct1_1_2_3(){ 75 AbstractBuilder* builder = new ConcreteBuilder1(); 76 vector<string> sequen; 77 sequen.push_back("operator1"); 78 sequen.push_back("operator2"); 79 sequen.push_back("operator3"); 80 builder->setSequence(sequen); 81 AbstractProduct* product = builder->getProduct(); 82 return product; 83 } 84 85 AbstractProduct* getConcreteProduct1_3_2_1(){ 86 AbstractBuilder* builder = new ConcreteBuilder1(); 87 vector<string> sequen; 88 sequen.push_back("operator3"); 89 sequen.push_back("operator2"); 90 sequen.push_back("operator1"); 91 builder->setSequence(sequen); 92 AbstractProduct* product = builder->getProduct(); 93 return product; 94 } 95 96 AbstractProduct* getConcreteProduct2_1_2_3(){ 97 AbstractBuilder* builder = new ConcreteBuilder2(); 98 vector<string> sequen; 99 sequen.push_back("operator1"); 100 sequen.push_back("operator2"); 101 sequen.push_back("operator3"); 102 builder->setSequence(sequen); 103 AbstractProduct* product = builder->getProduct(); 104 return product; 105 } 106 107 AbstractProduct* getConcreteProduct2_3_2_1(){ 108 AbstractBuilder* builder = new ConcreteBuilder2(); 109 vector<string> sequen; 110 sequen.push_back("operator3"); 111 sequen.push_back("operator2"); 112 sequen.push_back("operato1"); 113 builder->setSequence(sequen); 114 AbstractProduct* product = builder->getProduct(); 115 return product; 116 } 117 }; 118 int main(){ 119 120 Director* director = new Director(); 121 AbstractProduct* product1 = director->getConcreteProduct1_1_2_3(); 122 product1->execute(); 123 124 AbstractProduct* product2 = director->getConcreteProduct1_3_2_1(); 125 product2->execute(); 126 127 system("pause"); 128 return 0; 129 }