程序设计模式(三) C++ Builder模式

来源:互联网 发布:mac 股票交易 编辑:程序博客网 时间:2024/06/08 06:43
Builder模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

适用于以下情况:

1)当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。

2)当构造过程必须允许被构造的对象有不同的表示时。


思想:将一个类创建过程和他的主体部分分离。

场景:该模式的典型的应用场景是:一个类的创建过程可能比较复杂,或者创建过程中的某些阶段可能会容易变化;或者多个类的创建过程比较类似, 但是主体不同。

实现:在 以上提到的两种场景中,我们就可以取出一个类的创建过程的代码,定义一个专门的Builder类, 而在原来创建类对象实例的地方,将这个Builder类的实例作为参数传入。还有第二个重点,就是Builder类 可以将将整个创建过程分为几个阶段,每个阶段不必在类中直接实现,而可以通过继承体系在子类中实现,或者通过子类的方法过载来修改创建过程中的某个阶段, 但是重用其他的阶段。可以发现,该模式将一个对象的复杂创建过程重用到非常高的层次。这正是它的意义所在。

实例: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 Product11 {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 Builder26 {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 Builder38 {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 Builder52 {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 Director69 {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 }
复制代码

 

建造者模式和工厂模式非常相似呀,但是记住一点你就可以游刃有余的使用了:

建造者模式最主要功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了;

而工厂方法则重点是创建,你要什么对象我创造一个对象出来,组装顺序则不是他关心的。

建造者模式使用的场景,一是产品类非常的复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式是非常合适


重构成本:低。该模式的重构成本我觉得是非常低的,因为一般来讲,创建过程的代码本来也就应该在原来的类的构造函数中,把它Extract出 来就好了。如果发现多个类的创建过程有比较多的代码重复或类似,那么就可以重用这些提取出来的Builder类 或者Builder类中的某些阶段。实现:在 以上提到的两种场景中,我们就可以取出一个类的创建过程的代码,定义一个专门的Builder类, 而在原来创建类对象实例的地方,将这个Builder类的实例作为参数传入。还有第二个重点,就是Builder类 可以将将整个创建过程分为几个阶段,每个阶段不必在类中直接实现,而可以通过继承体系在子类中实现,或者通过子类的方法过载来修改创建过程中的某个阶段, 但是重用其他的阶段。可以发现,该模式将一个对象的复杂创建过程重用到非常高的层次。这正是它的意义所在。
重构成本:低。该模式的重构成本我觉得是非常低的,因为一般来讲,创建过程的代码本来也就应该在原来的类的构造函数中,把它Extract出 来就好了。如果发现多个类的创建过程有比较多的代码重复或类似,那么就可以重用这些提取出来的Builder类 或者Builder类中的某些阶段。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 墙面漆颜色刷深了怎么办 地板上沾了墙漆怎么办 孩子连发高烧8天了怎么办 孩子对数字不敏感怎么办 三岁宝宝不爱学习怎么办 5岁还不认识数字怎么办 小孩上中班还不认识数字怎么办 中班小孩数字都不认识怎么办 中班小孩记不住数字怎么办 中班小孩不肯练数字描红怎么办 2个月吃母乳婴儿缺钙怎么办 月经期接吻水多怎么办 4岁宝宝晚上尿多怎么办 2岁宝宝晚上尿多怎么办 3岁宝宝晚上尿多怎么办 宝宝拉肚子拉绿色的屎怎么办 婴儿吃奶粉大便干燥怎么办 母乳宝宝不拉大便怎么办 我儿子8岁拉肚子怎么办 1岁宝宝经常便秘怎么办 两个月宝宝拉水怎么办 宝宝吃奶粉上火便秘怎么办 20多天的宝宝便秘怎么办 宝宝五十天消化不良不拉屎怎么办 一周七个月宝宝消化不良拉屎怎么办 孩子总是消化不良拉屎不成型怎么办 一岁宝宝长牙慢怎么办 一岁宝宝不喝水怎么办 七个月的宝宝咳嗽怎么办 怀孕七个月感冒了怎么办 苹果汁弄到白色衣服怎么办 宝宝大便干燥拉不出来怎么办 婴儿吃过青菜米粉呕吐怎么办 50天宝宝便秘5天怎么办 8个月婴幼儿便秘怎么办 1个月婴幼儿便秘怎么办 榨汁后的苹果渣怎么办 宝宝6个月后容易生病怎么办 婴儿头型睡偏了怎么办 6个月婴儿不吃奶怎么办 宝宝秋季腹泻反复发烧怎么办