[设计模式之禅读书笔记]011_23种设计模式五:建造者模式
2012-11-01 00:35
411 查看
序言
建造者模式,这是一个无法从字面上推测出类图的模式,但是有了前面的模板方法模式的基础,在理解建造者模式上,会觉得很简单。我也尽量多用图来解释建造者模式,因为今天在看别人的文章的时候,我发现自己很懒,懒得看那一堆堆的文字。文字固然可以灵巧的组成散文诗歌,但是对于时间仓促,浮躁的程序员来说,如果不是需要这门技术,自己根本没闲心去看别人的文字。唉,序言有点罗嗦了,估计80%的人都不会完整的看完序言,不过没关系,看正文就行。
正文
1. 在脑子里形成一个需求图
稍微解释一下这个图,这个图定义了一个产品的模板,姑且叫产品这个名字吧!其中“执行”这个行为是“操作1”、“操作2”、“操作3”这三个操作的组合,不过,执行顺序是不定的,如何构造一个执行序列不一定的方法呢?我们可以靠数组来定义这个执行序列,参考下列代码:
2. 同一产品系列产品执行序列不同到底是何意?
这是一个扩充的需求图,不过,我特意标识的红字部分只有dota玩家能懂。不过没关系,我来解释一下,这里我们看到产品系列1和产品系列2中的操作是不同的,但是仍然符合产品模板的规定。其次,两个产品系列下,都有各自的产品。可以看出,在各个产品中,操作执行序列是不同的。也就是说,操作序列是最后定义的。
现在抛出一个问题,上面的模型该怎么设计呢?由于这节学习的建造者模式,所以,下面我们来一步一步来实现这个建造者模式。
3. 产品模板
产品模板很简单,定义三个操作和一个执行序列就可以了,但是我们还需要一个可以设置执行序列的数组,这个数组由一个方法来设置。代码如下:
聪明的小孩会看到,这不就是模板方法模式吗?把具体实现延迟到子类,父类定义好算法的框架,是的,没错,这就是模板方法模式。
2. 产品系列的实现
我们有两个产品系列,其中都实现了产品模板中没有实现的三个操作,那么两个产品系列是如何的呢?代码如下:
3. 具体产品的简单构建(从这一点可以看出我们需要建造者模式)
现在产品系列出来了,如何建立我们需要的产品呢?一般来说,你肯定会如下这么写:
这样写是可以得到我们需要的结果,但是,试想如果我需要很多个不同操作序列的产品,那我这个main里面是不是会很庞大?那该怎么改进呢?
4. 我们需要建造者
建造者长什么样呢?至少能不用让我们自己一直new产品吧!代码参考如下:
上面是两个产品系列的建造者,这个时候,我们的客户端调用就变成下面这个样子了:
看出来不同没?我们有Builder了,只要new一个Builder出来,下面我们就不用自己new各个产品了。那么这样的代码看起来还是不够明晰,main里面,即客户端调用的代码看起来还是不清爽,这时候我们需要引进一个新类——Director。
5. 隆重登场Director(封装了各种产品)
它的职责其实就是将上面main里面出现的那一堆代码封装起来,然后提供一些方法来构建我们的产品,代码参考如下:
6. 新的客户端调用(变得很简洁了)
引进了Director后,再来看看我们的客户端调用吧:
是不是很简洁了,这就是我们最终的结果!!!
UML图
我偷懒了,没有把方法放到里面,注意上面的红框内的组合,是一个模板方法模式,其他的咱就不多说了,自己研究研究吧!
总结
对于建造者模式的理解还仅限于代码而已,实际应用场景需要强化,我尽量找机会时间自己的建造者模式,呵呵!
PS:附上最终的完整代码:
建造者模式,这是一个无法从字面上推测出类图的模式,但是有了前面的模板方法模式的基础,在理解建造者模式上,会觉得很简单。我也尽量多用图来解释建造者模式,因为今天在看别人的文章的时候,我发现自己很懒,懒得看那一堆堆的文字。文字固然可以灵巧的组成散文诗歌,但是对于时间仓促,浮躁的程序员来说,如果不是需要这门技术,自己根本没闲心去看别人的文字。唉,序言有点罗嗦了,估计80%的人都不会完整的看完序言,不过没关系,看正文就行。
正文
1. 在脑子里形成一个需求图
稍微解释一下这个图,这个图定义了一个产品的模板,姑且叫产品这个名字吧!其中“执行”这个行为是“操作1”、“操作2”、“操作3”这三个操作的组合,不过,执行顺序是不定的,如何构造一个执行序列不一定的方法呢?我们可以靠数组来定义这个执行序列,参考下列代码:
void setSequence(vector<string> quen){ this->sequen = quen; } void execute(){ for(int i = 0; i < sequen.size(); i ++){ if(sequen[i].compare("operator1") == 0){ this->operator1(); }else if(sequen[i].compare("operator2") == 0){ this->operator2(); }else if(sequen[i].compare("operator3") == 0){ this->operator3(); } } }
2. 同一产品系列产品执行序列不同到底是何意?
这是一个扩充的需求图,不过,我特意标识的红字部分只有dota玩家能懂。不过没关系,我来解释一下,这里我们看到产品系列1和产品系列2中的操作是不同的,但是仍然符合产品模板的规定。其次,两个产品系列下,都有各自的产品。可以看出,在各个产品中,操作执行序列是不同的。也就是说,操作序列是最后定义的。
现在抛出一个问题,上面的模型该怎么设计呢?由于这节学习的建造者模式,所以,下面我们来一步一步来实现这个建造者模式。
3. 产品模板
产品模板很简单,定义三个操作和一个执行序列就可以了,但是我们还需要一个可以设置执行序列的数组,这个数组由一个方法来设置。代码如下:
class AbstractProduct{ public: virtual void operator1(){} virtual void operator2(){} virtual void operator3(){} void setSequence(vector<string> quen){ this->sequen = quen; } void execute(){ for(int i = 0; i < sequen.size(); i ++){ if(sequen[i].compare("operator1") == 0){ this->operator1(); }else if(sequen[i].compare("operator2") == 0){ this->operator2(); }else if(sequen[i].compare("operator3") == 0){ this->operator3(); } } } private: vector<string> sequen; };
聪明的小孩会看到,这不就是模板方法模式吗?把具体实现延迟到子类,父类定义好算法的框架,是的,没错,这就是模板方法模式。
2. 产品系列的实现
我们有两个产品系列,其中都实现了产品模板中没有实现的三个操作,那么两个产品系列是如何的呢?代码如下:
class ConcreteProduct1:public AbstractProduct{ void operator1(){ cout<<"Product1: operator1 executing."<<endl; } void operator2(){ cout<<"Product1: operator2 executing."<<endl; } void operator3(){ cout<<"Product1: operator3 executing."<<endl; } }; class ConcreteProduct2:public AbstractProduct{ void operator1(){ cout<<"Product2: operator1 executing."<<endl; } void operator2(){ cout<<"Product2: operator2 executing."<<endl; } void operator3(){ cout<<"Product2: operator3 executing."<<endl; } };
3. 具体产品的简单构建(从这一点可以看出我们需要建造者模式)
现在产品系列出来了,如何建立我们需要的产品呢?一般来说,你肯定会如下这么写:
int main(){ AbstractProduct* product = new ConcreteProduct1(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operator1"); product->setSequence(sequen); product->execute(); system("pause"); return 0; }
这样写是可以得到我们需要的结果,但是,试想如果我需要很多个不同操作序列的产品,那我这个main里面是不是会很庞大?那该怎么改进呢?
4. 我们需要建造者
建造者长什么样呢?至少能不用让我们自己一直new产品吧!代码参考如下:
class ConcreteBuilder1:public AbstractBuilder{ public: AbstractProduct *getProduct(){ return product; } void setSequence(vector<string> quen){ product = new ConcreteProduct1(); product->setSequence(quen); } private: ConcreteProduct1* product; }; class ConcreteBuilder2:public AbstractBuilder{ public: AbstractProduct *getProduct(){ return product; } void setSequence(vector<string> quen){ product = new ConcreteProduct2(); product->setSequence(quen); } private: ConcreteProduct2* product; };
上面是两个产品系列的建造者,这个时候,我们的客户端调用就变成下面这个样子了:
int main(){ AbstractBuilder* builder = new ConcreteBuilder1(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operator1"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); product->execute(); system("pause"); return 0; }
看出来不同没?我们有Builder了,只要new一个Builder出来,下面我们就不用自己new各个产品了。那么这样的代码看起来还是不够明晰,main里面,即客户端调用的代码看起来还是不清爽,这时候我们需要引进一个新类——Director。
5. 隆重登场Director(封装了各种产品)
它的职责其实就是将上面main里面出现的那一堆代码封装起来,然后提供一些方法来构建我们的产品,代码参考如下:
class Director{ public: AbstractProduct* getConcreteProduct1_1_2_3(){ AbstractBuilder* builder = new ConcreteBuilder1(); vector<string> sequen; sequen.push_back("operator1"); sequen.push_back("operator2"); sequen.push_back("operator3"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct1_3_2_1(){ AbstractBuilder* builder = new ConcreteBuilder1(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operator1"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct2_1_2_3(){ AbstractBuilder* builder = new ConcreteBuilder2(); vector<string> sequen; sequen.push_back("operator1"); sequen.push_back("operator2"); sequen.push_back("operator3"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct2_3_2_1(){ AbstractBuilder* builder = new ConcreteBuilder2(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operato1"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } };
6. 新的客户端调用(变得很简洁了)
引进了Director后,再来看看我们的客户端调用吧:
int main(){ Director* director = new Director(); AbstractProduct* product1 = director->getConcreteProduct1_1_2_3(); product1->execute(); AbstractProduct* product2 = director->getConcreteProduct1_3_2_1(); product2->execute(); system("pause"); return 0; }
是不是很简洁了,这就是我们最终的结果!!!
UML图
我偷懒了,没有把方法放到里面,注意上面的红框内的组合,是一个模板方法模式,其他的咱就不多说了,自己研究研究吧!
总结
对于建造者模式的理解还仅限于代码而已,实际应用场景需要强化,我尽量找机会时间自己的建造者模式,呵呵!
PS:附上最终的完整代码:
#include <iostream> #include <vector> using namespace std; class AbstractProduct{ public: virtual void operator1(){} virtual void operator2(){} virtual void operator3(){} void setSequence(vector<string> quen){ this->sequen = quen; } void execute(){ for(int i = 0; i < sequen.size(); i ++){ if(sequen[i].compare("operator1") == 0){ this->operator1(); }else if(sequen[i].compare("operator2") == 0){ this->operator2(); }else if(sequen[i].compare("operator3") == 0){ this->operator3(); } } } private: vector<string> sequen; }; class ConcreteProduct1:public AbstractProduct{ void operator1(){ cout<<"Product1: operator1 executing."<<endl; } void operator2(){ cout<<"Product1: operator2 executing."<<endl; } void operator3(){ cout<<"Product1: operator3 executing."<<endl; } }; class ConcreteProduct2:public AbstractProduct{ void operator1(){ cout<<"Product2: operator1 executing."<<endl; } void operator2(){ cout<<"Product2: operator2 executing."<<endl; } void operator3(){ cout<<"Product2: operator3 executing."<<endl; } }; class AbstractBuilder{ public: virtual AbstractProduct *getProduct(){ return NULL;} virtual void setSequence(vector<string> quen){} }; class ConcreteBuilder1:public AbstractBuilder{ public: AbstractProduct *getProduct(){ return product; } void setSequence(vector<string> quen){ product = new ConcreteProduct1(); product->setSequence(quen); } private: ConcreteProduct1* product; }; class ConcreteBuilder2:public AbstractBuilder{ public: AbstractProduct *getProduct(){ return product; } void setSequence(vector<string> quen){ product = new ConcreteProduct2(); product->setSequence(quen); } private: ConcreteProduct2* product; }; class Director{ public: AbstractProduct* getConcreteProduct1_1_2_3(){ AbstractBuilder* builder = new ConcreteBuilder1(); vector<string> sequen; sequen.push_back("operator1"); sequen.push_back("operator2"); sequen.push_back("operator3"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct1_3_2_1(){ AbstractBuilder* builder = new ConcreteBuilder1(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operator1"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct2_1_2_3(){ AbstractBuilder* builder = new ConcreteBuilder2(); vector<string> sequen; sequen.push_back("operator1"); sequen.push_back("operator2"); sequen.push_back("operator3"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } AbstractProduct* getConcreteProduct2_3_2_1(){ AbstractBuilder* builder = new ConcreteBuilder2(); vector<string> sequen; sequen.push_back("operator3"); sequen.push_back("operator2"); sequen.push_back("operato1"); builder->setSequence(sequen); AbstractProduct* product = builder->getProduct(); return product; } }; int main(){ Director* director = new Director(); AbstractProduct* product1 = director->getConcreteProduct1_1_2_3(); product1->execute(); AbstractProduct* product2 = director->getConcreteProduct1_3_2_1(); product2->execute(); system("pause"); return 0; }
相关文章推荐
- 23种设计模式(4):建造者模式
- Java 23种设计模式之建造者模式
- 23种设计模式----------建造者模式
- [设计模式之禅读书笔记]007_23种设计模式一:单例模式
- java_23种设计模式之建造者模式
- 23种设计模式之建造者模式(Builder)
- 模式对象GoF23种设计模式之创建型模式之建造者模式
- 23种设计模式(4):建造者模式
- 使用Object-C实现23种设计模式之建造者模式
- 23种设计模式(4):建造者模式
- Java开发中的23种设计模式之四:建造者模式(Builder)
- 23种设计模式(4):建造者模式
- 走穿java23种设计模式-4建造者模式详解
- 23种设计模式[4]:建造者模式
- 23种设计模式(4):建造者模式
- 23种设计模式之——建造者模式
- (转)23种设计模式(4):建造者模式(实例代码并不怎么好)
- GoF23种设计模式之创建型模式之建造者模式
- //c++ 23种设计模式之建造者模式2
- 重学java23种设计模式(3)建造者模式