设计模式:建造者模式

引言

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

简介

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

为什么需要这个建造者模式呢?如果没有这个模式,我们工厂里面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;
}

总结

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

相关推荐
wuminyu1 小时前
JUC组件逐层剥离与深度剖析
java·linux·c语言·jvm·c++·算法
独隅2 小时前
CLion 接入 Codex 的完整配置使用全面指南
c++·ide·ai·c++23
老洋葱Mr_Onion3 小时前
【C++】高精度模板
开发语言·c++·算法
梓仁沐白3 小时前
【Agent 设计模式】推理技术
设计模式
Kinghiee3 小时前
从使用场景切入前端常见设计模式
前端·设计模式
我不是懒洋洋4 小时前
从零实现一个分布式计算:MapReduce的核心设计
c++
小王C语言14 小时前
【7. 实现登录注册模块】:实现会话管理、注册/登录/退出 API
网络·c++
峥无16 小时前
C++11 深度详解:现代 C++ 基石全梳理
开发语言·c++·笔记
阿米亚波17 小时前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl