[設計模式之禪讀書筆記]011_23種設計模式五:建造者模式


   序言

   建造者模式,這是一個無法從字面上推測出類圖的模式,但是有了前面的模板方法模式的基礎,在理解建造者模式上,會覺得很簡單。我也盡量多用圖來解釋建造者模式,因為今天在看別人的文章的時候,我發現自己很懶,懶得看那一堆堆的文字。文字固然可以靈巧的組成散文詩歌,但是對於時間倉促,浮躁的程序員來說,如果不是需要這門技術,自己根本沒閑心去看別人的文字。唉,序言有點羅嗦了,估計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 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM