【C++设计模式】建造者模式

举报
野猪佩奇996 发表于 2022/02/21 23:40:16 2022/02/21
【摘要】 学习总结 建造者模式的优点: 建造者模式中,客户端不需要知道产品内部组成细节,将产品本身和产品的创建过程分离,使同样的创建过程可以创建不同的产品对象;不同建造者相互独立,并无任何挂链,方便替换。 ...

学习总结

  • 建造者模式的优点:
    • 建造者模式中,客户端不需要知道产品内部组成细节,将产品本身和产品的创建过程分离,使同样的创建过程可以创建不同的产品对象;
    • 不同建造者相互独立,并无任何挂链,方便替换。
  • 建造者模式的缺点:
    • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
    • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大
  • 适用环境:
    • 需要生成的产品对象有复杂的内部结构(通常包含多个成员变量);
    • 产品对象内部属性有一定的生成顺序;
    • 同一个创建流程适用于多种不同的产品。

一、建造者模式

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。如建房子的过程有打地基、筑墙、安装门窗等,但是可以按照用户的不同需求进行建造不同风格的房子。

1.1 建造者模式的结构

  • 抽象建造者(AbstractBuilder):创建一个Product对象的各个部件指定的抽象接口;
  • 具体建造者(ConcreteBuilder):实现AbstractBuilder的接口,实现各个部件的具体构造方法和装配方法,并返回创建结果。
  • 产品(Product):具体的产品对象
  • 指挥者(Director): 构建一个使用Builder接口的对象,安排复杂对象的构建过程,客户端一般只需要与Director交互,指定建造者类型,然后通过构造函数或者setter方法将具体建造者对象传入Director。它主要作用是:隔离客户与对象的生产过程,并负责控制产品对象的生产过程。

在这里插入图片描述

1.2 建造者模式的实例

造房子:
在这里插入图片描述

二、代码

2.1 头文件

(1)定义产品类House类,具有florrwallroot三个属性。
(2)定义2个抽象构造者AbstractBuilder,其构造函数即要new一个House实例对象,然后还有4个建墙、建地板等的纯虚函数。在后面的具体建造者类中重写纯虚函数。
(3)定义指挥者类Director类,这个类最重要也是最有挑战性的。含有抽象建造者对象AbstractBuilder、封装组装流程的House型方法(结果返回建造的结果)、setBuilder方法也是最有意思的(参数是AbstractBuilder *iBuilder,但我们是可以传入子类对象指针的,比如具体建造者A的对象指针,即用了多态)。

#include<string>
using namespace std;

//产品类House
class House{
public:
	//构造函数
	House(){}
	void setFloor(string iFloor){
		this->floor = iFloor;
	}
	void setWall(string iWall){
		this->wall = iWall;
	}
	void setRoof(string iRoof){
		this->roof = iRoof;
	}
	//打印House信息
	void printfHouseInfo(){
		printf("Floor:%s\t\n", this->floor.c_str());
		printf("Wall:%s\t\n", this->wall.c_str());
		printf("Roof:%s\t\n", this->roof.c_str());
	}
private:
	string floor;
	string wall;
	string roof;
};

//抽象建造者AbstractBall
class AbstractBuilder{
public:
	AbstractBuilder(){
		house = new House();
	}
	//抽象方法:
	virtual void buildFloor() = 0;
	virtual void buildWall() = 0;
	virtual void buildRoof() = 0;
	//纯虚函数,在具体建造者中进行
	virtual House *getHouse() = 0;
	//实例化房子类house对象
	House *house;
};

//具体建造者ConcreteBuilderA
class ConcreteBuilderA :public AbstractBuilder{
public:
	ConcreteBuilderA(){
		printf("ConcreteBuilderA\n");
	}
	//具体实现方法
	void buildFloor(){
		this->house->setFloor("Floor_A");
	}
	void buildWall(){
		this->house->setWall("Wall_A");
	}
	void buildRoof(){
		this->house->setRoof("Roof_A");
	}
	House *getHouse(){
		return this->house;
	}
};
 
//具体建造者ConcreteBuilderB
class ConcreteBuilderB :public AbstractBuilder{
public:
	ConcreteBuilderB(){
		printf("ConcreteBuilderB\n");
	}
	//具体实现方法
	void buildFloor(){
		this->house->setFloor("Floor_B");
	}
	void buildWall(){
		this->house->setWall("Wall_B");
	}
	void buildRoof(){
		this->house->setRoof("Roof_B");
	}
	House *getHouse(){
		return this->house;
	}
};

//指挥者Director
class Director{
public:
	Director(){}
	//具体实现方法
	void setBuilder(AbstractBuilder *iBuilder){
		this->builder = iBuilder;
	}
    //封装组装流程,返回建造结果
	House *construct(){
		builder->buildFloor();
		builder->buildWall();
		builder->buildRoof();
		return builder->getHouse();
	}
private:
	AbstractBuilder *builder;
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105

2.2 客户端代码

#include "BuilderPattern.h"
 
int main(){
	//抽象建造者
	AbstractBuilder *builder;
	//指挥者
	Director *director = new Director();
	//产品:House
	House *house;
 
	//指定具体建造者A
	builder = new ConcreteBuilderA();
	director->setBuilder(builder);
	house = director->construct();
	house->printfHouseInfo();
 
	//指定具体建造者B
	builder = new ConcreteBuilderB();
	director->setBuilder(builder);
	house = director->construct();
	house->printfHouseInfo();
 
	system("pause");
	return 0;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

在这里插入图片描述

  • 在客户端只需要指定具体建造者,并作为参数传递给指挥者,通过指挥者即可得到结果。客户端无需关心House的建造方法和具体流程。
  • 如果需要更换建造风格,只需要更换建造者即可。不同建造者之间木有联系,方便替换。
  • 从代码优化角度来看,其实可以不需要指挥者Director的角色,而直接把construct方法放入具体建造者当中。

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/123036947

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。