设计模式那点事--建造者模式
2015-07-07 17:33
134 查看
概念:
建造者模式(Builder),将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。我们只需指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需知道了。
例子:
一个鲜活简单的例子总能让人轻松地理解晦涩的概念。我们来看看一个关于构建汽车的建造者模式。
我们知道,汽车一般由轮胎,引擎和车身组成。就像宝马(BMW),法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们也是由这三种东西组成的,只不过构成模块价格不同。
对于它们来说,虽然组成模块价格不同,但是构建汽车都包含这三种东西,是一种公共操作。于是,可以创建一个抽象父亲汽车构建类(CarBuilder),声明三个构建函数virtual void BuildWheel等的接口。然后创建三个具体汽车构建子类:BMWBuilder,FerraliBuilder和BenzBuilder,用于具体汽车的构建,并提供返回具体汽车产品对象的接口。它们分别继承于CarBuilder,每个子类实现父类模块的个性化构建。
然后再定义一个构建汽车指导者CarDirector,用于控制汽车建造过程,隔离用户与建造过程的关联。最后定义一个产品类Product,用于显示最终的生成汽车产品。
角色:
1、建造者(Builder):为创建一个产品对象的各个部件指定抽象接口,如CarBuilder。
2、具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,提供一个获取汽车成品对象的接口,如BMWBilder。
3、指示领导者(Director):构造一个使用Builder接口的对象,用于控制建造过程,隔离用户与建造过程的关联,如CarDirector。
4、具体产品(Product):表示被构造的复杂对象,如BMW汽车。
UML图:
代码:
发散:
我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。虚函数实现的多态称为动态多态,上面代码有以下特点:
1、子类的对象转换给父类的对象如CarBuilder* cb= new BMWBuilder,我们称为向上转型。它是安全的,自动完成,并且会丢失子类型的信息;
2、为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数BuildWheel;
3、子类有完全相同的BuildWheel函数,覆盖重写父类的虚函数BuildWheel,这样便能实现动态多态了(否则只能用指针或引用了)。
应用场景:
1、当创建一些复杂对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建面临着复杂的变化;
2、当构造过程必须允许被构造的对象有不同表示时。
优点:
使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了,降低耦合性。
建造者模式(Builder),将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。我们只需指定需要建造的类型就可以得到它们,而具体建造的过程和细节就不需知道了。
例子:
一个鲜活简单的例子总能让人轻松地理解晦涩的概念。我们来看看一个关于构建汽车的建造者模式。
我们知道,汽车一般由轮胎,引擎和车身组成。就像宝马(BMW),法拉利(Ferrali)和奔驰(Benz)三辆汽车,它们也是由这三种东西组成的,只不过构成模块价格不同。
对于它们来说,虽然组成模块价格不同,但是构建汽车都包含这三种东西,是一种公共操作。于是,可以创建一个抽象父亲汽车构建类(CarBuilder),声明三个构建函数virtual void BuildWheel等的接口。然后创建三个具体汽车构建子类:BMWBuilder,FerraliBuilder和BenzBuilder,用于具体汽车的构建,并提供返回具体汽车产品对象的接口。它们分别继承于CarBuilder,每个子类实现父类模块的个性化构建。
然后再定义一个构建汽车指导者CarDirector,用于控制汽车建造过程,隔离用户与建造过程的关联。最后定义一个产品类Product,用于显示最终的生成汽车产品。
角色:
1、建造者(Builder):为创建一个产品对象的各个部件指定抽象接口,如CarBuilder。
2、具体建造者(ConcreteBuilder):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,提供一个获取汽车成品对象的接口,如BMWBilder。
3、指示领导者(Director):构造一个使用Builder接口的对象,用于控制建造过程,隔离用户与建造过程的关联,如CarDirector。
4、具体产品(Product):表示被构造的复杂对象,如BMW汽车。
UML图:
代码:
#pragma warning(disable : 4786) #include <iostream> #include <vector> #include <string> using namespace std; //具体产品类 class Product { public: vector<string> st; public: void AddParts(string sValue) { st.push_back(sValue); } void Show() { for (vector<string>::iterator stIter=st.begin(); stIter!=st.end(); stIter++) { cout<<*stIter<<endl; } } }; //建造者类 class CarBuilder { public: virtual void BuildWheel() { cout<<"CarBuilder:bulid wheel."<<endl; } virtual void BuildEngine() { cout<<"CarBuilder:bulid engine."<<endl; } virtual void BuildBody() { cout<<"CarBuilder:bulid body."<<endl; } }; //具体builder类,用于建造出具体产品 //实现CarBuilder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并 提供一个检索产品的接口 class BMWBuilder:public CarBuilder { public: Product product; public: void BuildWheel() { product.AddParts("BMW:bulid wheel."); } void BuildEngine() { product.AddParts("BMW:bulid engine."); } void BuildBody() { product.AddParts("BMW:bulid body."); } Product GetProduct() { return product; } }; class FerraliBuilder:public CarBuilder { public: Product product; public: void BuildWheel() { product.AddParts("Ferrali:bulid wheel."); } void BuildEngine() { product.AddParts("Ferrali:bulid engine."); } void BuildBody() { product.AddParts("Ferrali:bulid body."); } Product GetProduct() { return product; } }; class BenzBuilder:public CarBuilder { public: Product product; public: void BuildWheel() { product.AddParts("Benz:bulid wheel."); } void BuildEngine() { product.AddParts("Benz:bulid engine."); } void BuildBody() { product.AddParts("Benz:bulid body."); } Product GetProduct() { return product; } }; //指挥者,用于控制建造过程,隔离用户与建造过程的关联 class CarDirector { private: CarBuilder* cb; public: CarDirector(CarBuilder* cb) { this->cb = cb; } ~CarDirector() { if (cb!=NULL) { delete cb; cb = NULL; } } void CreateCar() { cb->BuildWheel(); cb->BuildEngine(); cb->BuildBody(); } }; int main() { int iTag=0; Product product; cout<<"----建造者模式开始----"<<endl; cout<<"BMW:1,Ferrali:2,Benz:3"<<endl; cout<<"请输入您想要构建的汽车:"; cin>>iTag; if(iTag==1) { BMWBuilder* bb= new BMWBuilder; CarDirector cd(bb); cd.CreateCar(); product = bb->GetProduct(); product.Show(); } else if(iTag==2) { FerraliBuilder* fb= new FerraliBuilder; CarDirector cd(fb); cd.CreateCar(); product = fb->GetProduct(); product.Show(); } else if(iTag==3) { BenzBuilder* bb= new BenzBuilder; CarDirector cd(bb); cd.CreateCar(); product = bb->GetProduct(); product.Show(); } cout<<"----建造者模式结束----"<<endl; return 1; }
发散:
我们知道实现C++的多态有三种方法:函数重载,模板函数和虚函数。虚函数实现的多态称为动态多态,上面代码有以下特点:
1、子类的对象转换给父类的对象如CarBuilder* cb= new BMWBuilder,我们称为向上转型。它是安全的,自动完成,并且会丢失子类型的信息;
2、为了解决子类型信息丢失的问题(子类对象转换给父类),父类必须实现了一个虚函数BuildWheel;
3、子类有完全相同的BuildWheel函数,覆盖重写父类的虚函数BuildWheel,这样便能实现动态多态了(否则只能用指针或引用了)。
应用场景:
1、当创建一些复杂对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建面临着复杂的变化;
2、当构造过程必须允许被构造的对象有不同表示时。
优点:
使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了,降低耦合性。
相关文章推荐
- 74LV165与74HC595 使用
- reactor和proactor模式
- Maven下载Jar包同时下载source和javadoc
- windows端口占用及结束进程
- android仿IOS,滑动隐藏底部ScrollView
- POJ 1984 Navigation Nightmare (数据结构-并检查集合)
- redis命令参考(三) List列表相关
- hive编程指南--employees表数据定义
- JAVA & Eclipse 笔记
- Android蓝牙通信详解
- LeetCode之Simplify Path
- iOS-ui-UISlider
- meteor中分页库alethes:pages用法汇总
- C# snaps
- 我的Android进阶之旅------>Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法
- debian_用iso文件创建本地apt源
- haproxy 页面重定向(域名跳转)
- C#自动更新
- XSD (xml Schema Definition)
- 基于注解的SpringMVC简单介绍