设计模式-建造者模式C++
一、定义
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式的基本思想是使用简单对象一步步构建一个复杂的对象。属于创建型模式。
建造者模式更关注各对象的组装过程,实现各个部件相互独立,并组装为复杂整体的作用。
二、建造者模式实例
每逢中秋,各商家都会生产出带有各种包装,用于各种场合的月饼产品。因为月饼产品除了月饼不可或缺外,由于使用场景不同,客户可能对产品的包装有不同的需求,这就导致“构建”月饼产品十分的复杂。
我们以“构建”这样的月饼产品为例。首先,我们假设我们的产品可能需要下列部件:
月饼(需要明确口味)、内包装、外包装、礼品袋。即具有这些成员的月饼类
class Mooncake
{string _filling; //月饼口味string _innerPackaging; //内包装string _outerPackaging; //外包装string _giftBags; //礼品袋包装
}
对于目标:构建出一件月饼产品,我们有如下方法
1、折叠式构造方法
定义一批构造函数,覆盖对必选和可选部件的组合,在构造时确认组装产品的部件
//折叠式构造方式
class Mooncake
{
public:Mooncake(string filling) : _filling(filling) {}Mooncake(string filling, string innerPackaging) : _filling(filling), _innerPackaging(innerPackaging) {}Mooncake(string filling, string innerPackaging, string outerPackaging) : _filling(filling), _innerPackaging(innerPackaging), _outerPackaging(outerPackaging) {}Mooncake(string filling, string innerPackaging, string outerPackaging, string giftBags) : _filling(filling), _innerPackaging(innerPackaging), _outerPackaging(outerPackaging), _giftBags(giftBags) {}//...这还不止,还需要其他组合。例如_filling + _outerPackaging的。以下都省略
private:string _filling; //月饼口味(必选)string _innerPackaging; //内包装string _outerPackaging; //外包装string _giftBags; //礼品袋包装
};int main()
{//内包装为纸盒的五仁馅月饼产品Mooncake *moonCake = new Mooncake("五仁",“纸盒”);
}
2、对外暴露部件设置,使各部件可以构造后再设置
class Mooncake
{
public:Mooncake() :_filling(""),_innerPackaging(""),_outerPackaging(""),_giftBags("") {}virtual ~Mooncake() {}//內馅在子类实现确认void SetFilling(string param){_filling = param;}void SetInnerPackaging(string param){_innerPackaging = param;}void SetOuterPackaging(string param){_outerPackaging = param;}void SetGiftBags(string param){_giftBags = param;}protected:string _filling; //月饼口味string _innerPackaging; //内包装string _outerPackaging; //外包装string _giftBags; //礼品袋包装
};int main()
{Mooncake *moonCake = new Mooncake();moonCake -> SetFilling("五仁");moonCake -> SetOuterPackaging("一次性方便袋");
}
但是上述2都有些显然的缺点。
使用方法1的构造函数要时刻注意传参的顺序是否错误,因为一旦传参太多,容易造成混乱,对可读性也不是很友好。而且一旦构建的可能组合太多,会需要大量构造函数。
使用方法2,虽然可以很方便地传入正确参数,将“部件”设置正确,也足够灵活。但是对象中的属性是分步设置的,在没有构建完成时,产品对象就已经对外暴露了,容易发生错误。
对于以上需求,我们可以用建造者模式解决。
3、建造者模式的实现
1)月饼产品类,提供对外设置属性的接口,但是和2方法不同
class Mooncake
{
public:Mooncake() :_filling(""),_innerPackaging(""),_outerPackaging(""),_giftBags("") {}virtual ~Mooncake() {}//內馅在子类实现确认void SetFilling(string param){_filling = param;}void SetInnerPackaging(string param){_innerPackaging = param;}void SetOuterPackaging(string param){_outerPackaging = param;}void SetGiftBags(string param){_giftBags = param;}void Introduce(){cout << "这款月饼是" << _filling << "馅的" << endl;if ("" != _innerPackaging){cout << "内包装采用" << _innerPackaging << endl;}else{cout << "无内包装" << endl;}if ("" != _outerPackaging){cout << "外包装采用" << _outerPackaging << endl;}else{cout << "无外包装" << endl;}if ("" != _giftBags){cout << "具有" << _giftBags << "的礼品袋" << endl;}cout << "您看是否符合您的需求。" << endl;}
protected:string _filling; //月饼口味string _innerPackaging; //内包装string _outerPackaging; //外包装string _giftBags; //礼品袋包装
};
2)构建者抽象类,声明构建月饼产品的接口,用于规范化产品的构建,一般由子类具体实现构建方法
class Builder
{
public:virtual ~Builder() {}virtual void buildFilling() = 0; //构建內馅virtual void buildInnerPackaging(string param) = 0; //构建内包装virtual void buildOuterPackaging(string param) = 0; //构建外包装virtual void buildGiftBags(string param) = 0; //构建礼品袋virtual Mooncake* build() = 0; //对外提供构建的对象的指针
protected:Mooncake *_moonCake; //待构建的对象指针
};
3)构建者具体类-五仁月饼构建者(filling属性可以确认),可以具体实现对目标对象的构建
class FiveNutsMooncakeBuilder :public Builder
{
public:FiveNutsMooncakeBuilder(){_moonCake = new Mooncake();}~FiveNutsMooncakeBuilder(){if (nullptr != _moonCake){delete _moonCake;_moonCake = nullptr;}}void buildFilling(){if (nullptr != _moonCake){_moonCake->SetFilling("五仁");}}void buildInnerPackaging(string param){if (nullptr != _moonCake){_moonCake->SetInnerPackaging(param);}}void buildOuterPackaging(string param){if (nullptr != _moonCake){_moonCake->SetOuterPackaging(param);}}void buildGiftBags(string param){if (nullptr != _moonCake){_moonCake->SetGiftBags(param);}}Mooncake* build(){return _moonCake;}
};
4)指挥者类,传入构建者对象,指挥构建者对产品的构建过程。在这个案例中,我写了两种组建方案:简单包装和精美包装。虽然里面的月饼可能是相同的产品,但是大家都知道这肯定是2种价格~
class Director
{
public:Director(Builder* bd) :_builder(bd) {}~Director(){if (nullptr != _builder){delete _builder;_builder = nullptr;}}//简单包装的月饼产品Mooncake* SimplePackaging(){if (nullptr != _builder){_builder->buildFilling();_builder->buildOuterPackaging("纸盒");return _builder->build();}}//精美包装的月饼产品Mooncake* GiftPackaging(){if (nullptr != _builder){_builder->buildFilling();_builder->buildInnerPackaging("纸盒");_builder->buildOuterPackaging("精美铁盒");_builder->buildGiftBags("礼品袋");return _builder->build();}}private:Builder* _builder;
};
5)使用
int main(int argc, char *argv[])
{Builder *builder = new FiveNutsMooncakeBuilder();Director *direstor = new Director(builder);cout << "顾客A:" << endl;//获取已经“建造”好的月饼产品Mooncake* moonCakeA = direstor->GiftPackaging();//输出介绍话术moonCakeA->Introduce();system("pause");return 0;
}
6)这样构建的产品对象,方便扩展。假如想要增加别的月饼产品,比如增加什锦月饼。则我们就可以新增一个构建者。
class MixedMooncakeBuilder :public Builder
{
public:MixedMooncakeBuilder(){_moonCake = new Mooncake();}~MixedMooncakeBuilder(){if (nullptr != _moonCake){delete _moonCake;_moonCake = nullptr;}}void buildFilling(){if (nullptr != _moonCake){_moonCake->SetFilling("什锦");}}void buildInnerPackaging(string param){if (nullptr != _moonCake){_moonCake->SetInnerPackaging(param);}}void buildOuterPackaging(string param){if (nullptr != _moonCake){_moonCake->SetOuterPackaging(param);}}void buildGiftBags(string param){if (nullptr != _moonCake){_moonCake->SetGiftBags(param);}}Mooncake* build(){return _moonCake;}
};
三、总结
1、优缺点
该模式的主要优点如下:
1)封装性好,构建和表示分离;
2)扩展性好,各个具体的建造者相互独立,有利于系统的解耦;
3)客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
其缺点如下:
1)产品的组成部分必须相同,这限制了其使用范围。
2)如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
2、建造者模式的适用场景
1、需要构建的对象相对复杂,具有多个属性,并且有些属性具有默认值;
2、相同的方法,不同的执行顺序,产生不同的结果;
3、多个部件,可以装配到一个对象中,但是不同组合产生的结果又不相同;
创建的产品具备复杂创建过程时,可以抽取出共性创建过程,然后交由指挥者类自定义创建流程,使得同样的创建行为可以(传入不同构建者)生产出不同的产品,分离了创建与表示,使创建产品的灵活性大大增加。
【参考&致谢】
设计模式之建造者(Builder)模式 | 菜鸟教程 (runoob.com)https://www.runoob.com/w3cnote/builder-pattern.html建造者模式(Bulider模式)详解 (biancheng.net)http://c.biancheng.net/view/1354.html
设计模式-建造者模式C++相关推荐
- Python设计模式-建造者模式
Python设计模式-建造者模式 代码基于3.5.2,代码如下; #coding:utf-8 #建造者模式 class Burger():name = ""price = 0.0d ...
- 说说设计模式~建造者模式(Builder)
建造者模式是我的"设计模式"里创建型模式里的最后一篇,这种模式在实现中,很多架构都用到了,如MVC,MVP,MVVM,它们都是有建造者模式的精髓的,即,创建与表现分享,我们的MVC ...
- 设计模式 建造者模式_设计模式:建造者
设计模式 建造者模式 有时需要在应用程序中创建一个复杂的对象. 一种解决方案是Factory模式,另一种是Builder设计模式. 在某些情况下,您甚至可以结合使用这两种模式. 但是在本文中,我想研究 ...
- 设计建造者模式java代码,Java设计模式-建造者模式
定义 Separate the construction of a complex object from its representation so that the sameconstructio ...
- python创造者_python 设计模式-建造者模式
问题:在上一篇python设计模式:抽象工厂模式中,我们尝试用抽象工厂模式规范化了 Pizza 原材料的供应以及 Pizza 的创建.但是我们忽略了一个问题,那就是每种 Pizza 的烘焙时间依赖于生 ...
- java设计模式-建造者模式
概念:使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. ...
- 设计模式-建造者模式(转自:http://www.cnblogs.com/cbf4life/archive/2010/01/14/1647710.html)...
11.1 变化是永恒的 又是一个周三,快要下班了,老大突然拉住我,喜滋滋地告诉我:"牛叉公司很满意我们做的模型,又签订了一个合同,把奔驰.宝马的车辆模型都交给我们公司制作了,不过这次又额外增 ...
- 大话设计模式—建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 一个 Builder 类会一步一步构造最 ...
- 我的Java设计模式-建造者模式
在未上大学之前,一直有个梦想"I have a dream!",就是能成为一位汽车工程师,一直幻想着开着自己设计的汽车飞奔在公路上,迷倒了万千少女.咳咳~~虽然现在没实现我的dre ...
- Java常用设计模式————建造者模式
引言 建造者模式(Builder Pattern)使用多个简单对象一步一步构建成一个复杂的对象.这种类型的设计模式属于建造型模式,它提供了一种创建对象的最佳方式. 一个Builder会一步步构建最终的 ...
最新文章
- hurst代码 python_python数据类型—字符串
- scala成长之路(2)对象和类
- 中文NER任务实验小结:BERT-MRC的再优化
- 对称振子天线matlab程序,对称振子天线详解.ppt
- JAVA两个视图层_MVC - 管理帐户 . 一个视图有两个局部视图和两个模型
- 编译速度谁“最快”?25岁的 C++Builder 还能打
- 现在论文用手写还是用计算机写,毕业论文计算机手写数字识别技术完整版.docx...
- 将查询出来的数据按照一个字段分组且排序过程中,遇到的一些有关group的问题(分组排序应该使用partition by)
- Destroy与DestroyImmediate以及引发的bug
- 维护LINQ to SQL多对多表间关系[转]
- 手机辅助java脚本_android 手机一个辅助阅读工具
- linux免杀工具,安卓Apk免杀工具:backdoor-apk 教程
- python numpy 中linspace函数
- python调用WinRAR暴力获取压缩密码 用网址做解压密码
- 艺龙的执着与固执:等待微信
- Linux查看文件数量
- AOP底层实现原理、基于注解的AOP编程、AOP开发中的一个坑 打卡第八天
- 和导师闹僵跑来实习?拼了命也要拿到大厂实习offer
- OpenWrt之DNS域名解析系统(/etc/resolv.conf)
- conda 查看现有虚拟环境 - 删除现有虚拟环境