C++设计模式之建造者模式(builder)(创建型)
软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。
建造者模式Buider(又叫生成器模式、构造者模式)是属于创建性的设计模式,它将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。主要用于一步一步创建一个较复杂的对象,通过使用Builder模式向用户隐藏内部构建的细节,专注于控制对象的组装流程,从而达到将构建复杂对象的过程和其他部件解耦,最终实现两个自由扩展构建流程和部件。
Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder模式强调的是在导向者的控制下一步一步构造产品的,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。创建者模式可以能更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。
对于客户来说,只需知道导向者就可以了,通过导向者,客户就能构造复杂的对象,而不需要知道具体的构造过程。
Builder模式的优点
使得建造代码与表示代码分离,具有良好的封装性和独立性,对客户隐藏了该产品是如何组装的,既产品内部的实现和组成细节模块之间相对独立,耦合度不高有利于程序扩展,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。
Builder模式的缺点
由于产品自身的组成复杂和组成流程复杂,可能会产生额外的副产品,消耗额外的内存资源,比如说额外的Builder对象和Director对象等。
Builder模式场景
•复杂的对象内部构造间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。
•当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
•当构造过程必须允许被构造的对象有不同的表示时。
ULM图
构建模式的组成
• 抽象建造者角色(Builder):为创建一个Product对象的各个部件指定抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此角色规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
• 具体建造者(ConcreteBuilder)
1)实现Builder的接口以构造和装配该产品的各个部件。即实现抽象建造者角色Builder的方法。
2)定义并明确它所创建的表示,即针对不同的商业逻辑,具体化复杂对象的各部分的创建
3) 提供一个检索产品的接口
4) 构造一个使用Builder接口的对象即在指导者的调用下创建产品实例
• 指导者(Director):调用具体建造者角色以创建产品对象的各个部分。指导者并没有涉及具体产品类的信息,真正拥有具体产品的信息是具体建造者对象。它只负责保证对象各部分完整创建或按某种顺序创建。
• 产品角色(Product):建造中的复杂对象。它要包含那些定义组件的类,包括将这些组件装配成产品的接口。
Builder模式的主要效果:
1 ) 它使你可以改变一个产品的内部表示 Builder对象提供给导向器一个构造产品的抽象接口。该接口使得生成器可以隐藏这个产品的表示和内部结构。它同时也隐藏了该产品是如何装配的。因为产品是通过抽象接口构造的,你在改变该产品的内部表示时所要做的只是定义一个新的生成器。
2) 它将构造代码和表示代码分开 Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息;这些类是不出现在Builder接口中的。每个Concrete Builder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同的Product。3 ) 它使你可对构造过程进行更精细的控制 Builder模式与一下子就生成产品的创建型模式不同,它是在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回它。因此Builder接口相比其他创建型模式能更好的反映产品的构造过程。这使你可以更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。
这里我们介绍一个制造玩具的简单例子,对于建造一个奥特曼和蜘蛛侠的玩具来说,建造流程是稳定的:头--->身体--->四肢。对于这两个产品来说,具体的实现可能不同。在这个例子里为了让不同的奥特曼有差别,在用户端可以通过输入参数来控制。
实现代码:
#include <iostream>
#include <vector>
#include <string>//产品类有多个组件组成
class Product
{
public://添加组件void add(const std::string& componentName){components.emplace_back(componentName);}//移除组件void remove(const std::string& componentName){for (auto iter = components.begin(); iter != components.end();){if (*iter == componentName){iter = components.erase(iter);}else{iter++;}}}//显示产品组件void show(){std::cout << "显示产品的组件:" << std::endl;for (const auto& item : components){std::cout << item << std::endl;}std::cout << std::endl;}private:std::vector<std::string> components;
};//抽象建造者
class Builder
{
public:virtual void buildHead() = 0; //构建头virtual void buildBody() = 0; //构建身体virtual void buildLimbs() = 0; //构建四肢virtual Product* getProduct() = 0;virtual ~Builder() = default;
};//奥特曼具体构造者
class UltramanBuilder : public Builder
{
public:UltramanBuilder(const std::string head,const std::string body,const std::string limbs): head{head}, body{body}, limbs{limbs}{std::cout << "创建奥特曼." << std::endl;ultraman = new Product();}~UltramanBuilder(){delete ultraman;}void buildHead() override{ultraman->add("奥特曼头" + head);}void buildBody() override{ultraman->add("奥特曼身体" + body);}void buildLimbs() override{ultraman->add("奥特曼四肢" + limbs);}Product* getProduct() override{return ultraman;}
private:Product* ultraman;const std::string head;const std::string body;const std::string limbs;
};//蜘蛛侠具体构造者
class SpidermanBuilder : public Builder
{
public:SpidermanBuilder(){std::cout << "创建蜘蛛侠." << std::endl;spiderman = new Product();}~SpidermanBuilder(){delete spiderman;}void buildHead() override{spiderman->add("蜘蛛侠头");}void buildBody() override{spiderman->add("蜘蛛侠身体");}void buildLimbs() override{spiderman->add("蜘蛛侠四肢");}Product* getProduct() override{return spiderman;}
private:Product* spiderman;
};//指挥者类
class Director
{
public:void Construct(Builder* builder){builder->buildHead();builder->buildBody();builder->buildLimbs();}
};//客户端
int main()
{Director* director = new Director();std::cout << "指挥者用UltramanBuilder的方法创建产品:";UltramanBuilder* ultramanBuilder = new UltramanBuilder("有两个犄角", "带有XX特能", "手握YY剑");director->Construct(ultramanBuilder);Product* ultraman = ultramanBuilder->getProduct();ultraman->show();std::cout << std::endl;std::cout << "指挥者用SpidermanBuilderr的方法创建产品:";SpidermanBuilder* spidermanBuilder = new SpidermanBuilder();director->Construct(spidermanBuilder);Product* spiderman = spidermanBuilder->getProduct();spiderman->show();std::cout << std::endl;delete director;delete ultramanBuilder;delete spidermanBuilder;return 0;
}
结果如下:
在这里UltramanBuilder和SpidermanBuilder两个具体创建者的构造函数不用,主要是为了说明,客户也可以通过传入参数来创建UltramanBuilder这样的产品,通过参数的不同就可以得到不同的细微差别的复杂对象。例如,创建不同的奥尔曼(不同奥特曼头,身体,四肢不同)。
C++设计模式之建造者模式(builder)(创建型)相关推荐
- 23天读懂23种设计模式:原型模式(创建型)
点击上方 蓝字 关注我们 创建型模式是用来创建对象的模式,抽象了实例化的过程,帮助一个系统独立于其他关联对象的创建.组合和表示方式. 原型模式目的:用原型实例指定创建对象的种类,并且通过拷贝这些原型创 ...
- Android设计模式之建造者模式builder
今天小编来说一下Android中的一种设计模式--建造者模式Builder 绪论: 那么对于Android初级来说,Builder设计模式可能在我们开发中用过的很少,但是我们可能见过,我们经常用的Al ...
- Python 设计模式之建造者模式 Builder Pattern
#引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...
- UE4 C++设计模式:建造者模式(Builder Pattern)
目录 描述 套路 使用场景 优缺点 UE4实践 具体复杂产品-门派角色 抽象建造者-角色构造器 具体建造者-纯阳角色构造器 具体建造者-七秀角色构造器 创建指挥者(Director)-角色创建指挥器 ...
- 创建型设计模式之建造者模式(Builder)
结构 意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 当构造过程必须允许被构造的对象有不 ...
- 07、人人都会设计模式:建造者模式--Builder
PS:转载请注明出处 作者: TigerChain 地址: http://www.jianshu.com/p/300cbb9ee7f2 本文出自 TigerChain 简书 人人都会设计模式 教程简介 ...
- 一天一个设计模式之建造者模式(Builder)
建造者模式,属于创建型模式,其目的在于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 适用情况: • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. ...
- 设计模式之—建造者模式(Builder)-Java实现
Builder模式,将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部 表象的产品对象.建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节.建造模式可以 ...
- GOF23(3)之建造者模式(创建型模式)
1.场景 我们需要建造一个比较复杂的产品,如神舟飞船.这个产品创建起来非常的复杂,它肯定是由很多的零件先组成组件,然后组件再组成产品的,那么就会涉及到组件组装的顺序问题. 实际开发中,我们所需要的对象 ...
最新文章
- python2 与 python3的区别整理
- 【教程】Linux DNS 服务器安装、配置及维护
- 春风吹用计算机的谱子,方大同《春风吹》简谱
- word List 34
- Android PreferenceActivity 使用
- 培养“资源意识”,有助于职场晋升
- 使用python对文档的所有词组统计
- 辣条社区:问题解答、面试系列、求职助力、学习资源,你需要的都在这里
- 六石管理学: 头目们是如何忽略产品质量的
- 小米路由器 网站服务器地址,小米路由器设置网址
- SVN的下载和文件更新
- 我将出席 .NET Day in China 的圆桌讨论:探讨开发者就业话题
- ubntu 五笔输入法 打不出词组
- 【Linux】U-Boot启动文件start.S详解(超详细讲解,上篇)
- 一行Python都可以做什么?这35行看懂十行就算入门,全能看懂必是高手
- 【计网知识点总结】2 物理层
- ann flann alglibB最近邻方法时效性探索
- wps打开html文件乱码,wps文档打开以后乱码为什么
- ALV 下载到EXCEL里出现的问题
- Blender图解教程:设置参考图