设计模式:建造者模式

引言

本篇文章会通过代码和文字的配合来帮助理解建造者模式

简介

建造者模式解决的问题主要是怎么创建一个产品,比如说一个计算机,里面有很多的零部件,我们应该要怎么组装这些零部件变成一个计算机,这个就是建造者模式解决的问题。我们经常和工厂模式相互利用,因为工厂模式解决的问题是创建一个什么对象,而怎么创建的内部细节是由建造者模式解决。

为什么需要这个建造者模式呢?如果没有这个模式,我们工厂里面new出一个对象之后,就用set一个一个的设置属性,但是一旦业务需求发生变动,那就必须要在千万行代码里面找到那个对应的属性然后进行修改,这不符合开闭原则。而我们的建造者干的事情就是把装那些材料交给具体的建造者,按照什么顺序装交给指导员。

建造者模式并不是没有缺点,如果产品之间差距比较大,没有什么共同的特点,那么我们可能就需要非常非常多的建造者,换句话来说我们可以把很多个种类的产品大致总结成一个大类,最后返回的也是这一个大类。

代码

这个是Human的总类,里面交代了一个人类的特性,而我们如果要创建一个人,那么就需要对这些特性进行组装。

cpp 复制代码
#pragma once
#ifndef _HUMAN_H_
#define _HUMAN_H_
#include "../../Macros.h" // 宏定义
#include <string>
#include <iostream>

namespace bp {
	class Human {
		CC_SYNTHESIZE(std::string, type, Type);
		CC_SYNTHESIZE(std::string, region, Region);
	public:
		void printInfo() {
			std::cout << "type: " << type << std::endl;
			std::cout << "region: " << region << std::endl;
		}
	};
}

#endif

紧接着我们需要设置一个建造者的基类,这个建造者有两个事情,一个是提供设置特性的一个模板函数,方便子类重写,一个是这个建造者的保护类里有Human类型变量,这个是方便子类的不同建造者对human进行组装,然后针对这个变量,设置build()函数,并返回对应的指针(也就是构造完成之后的human)。注意:一个建造者对应一个human

cpp 复制代码
#pragma once
#ifndef _HUMANBUILDER_H_
#define _HUMANBUILDER_H_
#include "../../../Macros.h" // 宏定义
#include "../Human.h" 
#include <string>

namespace bp {
	class HumanBuilder {
	protected:
		Human human;
	public:
		virtual HumanBuilder* buildType() = 0;
		virtual HumanBuilder* buildRegion() = 0;
		Human* build();
	};
}
#endif
cpp 复制代码
#include "HumanBuilder.h"



bp::Human* bp::HumanBuilder::build()
{
	return new Human(human);
}

这个是其中一个的human的建造,其功能就是对一个human的特性进行设置。

cpp 复制代码
#pragma once
#ifndef _WHITEMANBUILDER_H_
#define _WHITEMANBUILDER_H_
#include "HumanBuilder.h"
#include "../../../util/ClassHelper.h"

namespace bp {
	class WhiteManBuilder : public HumanBuilder {
		DECLARE_CLASS(WhiteManBuilder);
	public:
		WhiteManBuilder* buildType() override;
		WhiteManBuilder* buildRegion() override;
	};
}
#endif
cpp 复制代码
#include "WhiteManBuilder.h"

IMPLEMENT_CLASS(bp::WhiteManBuilder);

bp::WhiteManBuilder* bp::WhiteManBuilder::buildType()
{
	human.setRegion("白种人");
	return this;
}

bp::WhiteManBuilder* bp::WhiteManBuilder::buildRegion()
{
	human.setRegion("美洲人");
	return this;
}

最后就是指挥官,当我们创建一个指挥官之后,我们会给这个指挥官设置对应的一个建造者(可能是多个),然后我们会通过这个建造者来设置一个human的特性,然后对外面提供一个接口build(),返回的就是human指针,在这个build函数里面我们会根据传入的建造者来建造human

cpp 复制代码
#pragma once
#ifndef	_HUMANDIRECTOR_H_
#define _HUMANDIRECTOR_H_
#include "builder/HumanBuilder.h"

namespace bp {
	class HumanDirector {
		CC_SYNTHESIZE(HumanBuilder*, m_Builder, Builder);
	public:
		Human* build();
	};
}

#endif
cpp 复制代码
#include "HumanDirector.h"

bp::Human* bp::HumanDirector::build()
{
	return m_Builder
		->buildType()
		->buildRegion()
		->build();
}

最后就是我们的客户端了,首先我们先读配置文件(尽可能不改代码),然后拿到对应的建造者,随后我们创建一个指导员,把这个建造者给到指导员,那么这个指导员就可以调用build(),在这个函数里面就是调用传进来的建造者工作,最后返回human,然后这么一个human就构建完成了。

cpp 复制代码
#include "../../util/Properties.h"
#include "builder/HumanBuilder.h"
#include "../../util/ClassHelper.h"
#include "HumanDirector.h"
#include <vld.h>
using namespace bp;
int main() {
	CREATE_PROPERTIES(prop, conf);
	std::string cname = prop.getProperty("bp");

	GET_INSTANCE_BY_NAME(HumanBuilder*, builder, cname);

	HumanDirector director;
	director.setBuilder(builder);
	auto human = director.build();
	human->printInfo();
	delete builder;
	delete human;	
	return 0;
}

总结

本篇文章就到这里结束了!!!希望可以帮助大家理解~~~

相关推荐
老歌老听老掉牙8 小时前
案例 7:二维 Rosenbrock 函数最小值(香蕉函数)
c++·pso
Severus_black8 小时前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
杯子不吃紫菜11 小时前
LangGraph 体系实战(下):中断恢复、流式、子图与设计模式
单片机·嵌入式硬件·设计模式
xiaoye-duck13 小时前
《C++ 项目:手写大模型接入 SDK》DataManager数据管理模块:SQLite持久化存储
开发语言·数据库·c++·sqlite
是main不是漫14 小时前
【C++——类和对象(上)】筑基篇:以封装奠定面向对象之基
c语言·开发语言·c++
是2的10次方啊14 小时前
设计模式与生活⑳:楼里的事都找前台,你就再没见过师傅
设计模式
小七在进步1 天前
string的使用(1)
c++·visual studio
白杨尚青1 天前
C++进阶篇(六):map 和 set 的模拟实现——用红黑树封装 mymap/myset(迭代器 + operator[])
开发语言·c++·迭代器·stl·set·map·红黑树
kloc1 天前
聊天室项目入口网关子服务的实现
linux·c++
csdn_aspnet1 天前
C++ 3个有序点的方向(Orientation of 3 ordered points)
c++·算法