当前位置: 首页 > news >正文

Chapter7—建造者模式

建造者模式

1 概念

建造者模式是指将一个复杂对象的构造与它的表示分离,展现了对象内部创建的过程和细节,将创建对象的各个细节按照一定的顺序组装起来,形成一个完整的对象。建造者模式注重创建对象的过程,返回创建对象的结果。

2 意图(Intent)

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

3 动机(Motivate)

在软件系统中,有时候面临一个"复杂对象"的创建工作,其通常由各个部分的子对象用一定算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合到一起的算法却相对稳定。如何应对种变化呢?如何提供一种"封装机制"来隔离出"复杂对象的各个部分"的变化,从而保持系统中的"稳定构建算法"不随需求的改变而改变。其抽象的位置在于对象创建的细节步骤。

4 类图结构

在这里插入图片描述

5 角色定义

  • Builder(建造者):为创建一个Product对象的各个部件指定抽象接口,定义了构成产品的各个组件的构建标准,通常有多个步骤。
  • ConcreteBuilder(建造者实现):具体建造者,可以有多种实现,负责产品的组装但不包含整体建造逻辑。
  • Product(产品):复杂的产品类,构建过程相对复杂,需要其他组件组装而成。
  • Director(指导者):持有建造者接口引用的指导者类,指导建造者按一定的逻辑进行建造。

6 程序示例

机器人产品

类图关系
在这里插入图片描述

class Robot
{
public:Robot() = default;~Robot() = default;public:void SetHead(const string& strHead);void SetBody(const string& strBody);void SetHand(const string& strHand);void SetFeet(const string& strFeet);void Show();private:string m_strHead;string m_strBody;string m_strHand;string m_strFeet;
};void Robot::SetHead(const string &strHead)
{m_strHead = strHead;
}void Robot::SetBody(const string &strBody)
{m_strBody = strBody;
}void Robot::SetHand(const string &strHand)
{m_strHand = strHand;
}void Robot::SetFeet(const string &strFeet)
{m_strFeet = strFeet;
}void Robot::Show()
{qDebug() << "Head =" << m_strHead.c_str();qDebug() << "Body =" << m_strBody.c_str();qDebug() << "Hand =" << m_strHand.c_str();qDebug() << "Feet =" << m_strFeet.c_str();
}

机器人建造者抽象类

class BaseBuildRobot
{
public:BaseBuildRobot();virtual ~BaseBuildRobot();public:virtual void BuildHead() = 0;virtual void BuildBody() = 0;virtual void BuildHand() = 0;virtual void BuildFeet() = 0;std::shared_ptr<Robot> GetRobot();protected:std::shared_ptr<Robot> m_spRobot;
};BaseBuildRobot::BaseBuildRobot()
{m_spRobot = std::make_shared<Robot>();
}BaseBuildRobot::~BaseBuildRobot()
{// ...
}std::shared_ptr<Robot> BaseBuildRobot::GetRobot()
{return m_spRobot;
}

机器人建造者具体类

class BuildKukaRobot : public BaseBuildRobot
{
public:BuildKukaRobot() = default;~BuildKukaRobot() = default;public:void BuildHead() override;void BuildBody() override;void BuildHand() override;void BuildFeet() override;
};void BuildKukaRobot::BuildHead()
{m_spRobot->SetHead("Kuka机器人头部");
}void BuildKukaRobot::BuildBody()
{m_spRobot->SetBody("Kuka机器人身体");
}void BuildKukaRobot::BuildHand()
{m_spRobot->SetHand("Kuka机器人手部");
}void BuildKukaRobot::BuildFeet()
{m_spRobot->SetFeet("Kuka机器人脚部");
}

指导者类

class Director
{
public:Director(const std::shared_ptr<BaseBuildRobot>& spRobotBuilder);~Director() = default;public:void SetRobotBuilder(const std::shared_ptr<BaseBuildRobot>& spRobotBuilder);std::shared_ptr<Robot> Direct();        // 指导创建private:std::shared_ptr<BaseBuildRobot> m_spRobotBuilder;
};Director::Director(const std::shared_ptr<BaseBuildRobot> &spRobotBuilder) : m_spRobotBuilder(spRobotBuilder)
{// ...
}void Director::SetRobotBuilder(const std::shared_ptr<BaseBuildRobot> &spRobotBuilder)
{m_spRobotBuilder = spRobotBuilder;
}std::shared_ptr<Robot> Director::Direct()
{m_spRobotBuilder->BuildHead();m_spRobotBuilder->BuildBody();m_spRobotBuilder->BuildHand();m_spRobotBuilder->BuildFeet();return m_spRobotBuilder->GetRobot();
}

客户端测试程序

void ClientTest()
{std::shared_ptr<BaseBuildRobot> spBuildRobot = std::make_shared<BuildKukaRobot>();std::unique_ptr<Director> upDirector = std::make_unique<Director>(spBuildRobot);std::shared_ptr<Robot> spRobot = upDirector->Direct();spRobot->Show();
}

程序输出

Head = Kuka机器人头部
Body = Kuka机器人身体
Hand = Kuka机器人手部
Feet = Kuka机器人脚部

我们在实例中使用了一些C++的智能指针,方便内存的管理。

建筑施工的示例

类图结构

在这里插入图片描述

建筑物类

/*** @brief 建筑物类*/
class Building
{
public:Building() = default;~Building() = default;public:void SetBasement(const string& strBasement);            // 地基void SetWall(const string& strWall);                    // 墙体void SetRoof(const string& strRoof);                    // 屋顶void Show();private:vector<string> m_vecBuildingComponents;
};void Building::SetBasement(const string &strBasement)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strBasement);
}void Building::SetWall(const string &strWall)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strWall);
}void Building::SetRoof(const string &strRoof)
{m_vecBuildingComponents.emplace(m_vecBuildingComponents.begin(), strRoof);
}void Building::Show()
{for (auto& strComponent : m_vecBuildingComponents)qDebug() << strComponent.c_str();
}

施工方基类和别墅施工方、多层公寓施工方类

/*** @brief 施工方接口**/
class BaseBuilder
{
public:BaseBuilder() = default;virtual ~BaseBuilder() = default;public:virtual void BuildBasement() = 0;virtual void BuildWall() = 0;virtual void BuildRoof() = 0;virtual Building* GetBuilding() = 0;
};/*** @brief 别墅施工方**/
class HouseBuilder: public BaseBuilder
{
public:HouseBuilder();~HouseBuilder() = default;public:void BuildBasement() override;void BuildWall() override;void BuildRoof() override;Building* GetBuilding() override;private:Building* m_pHouseBuilding;
};HouseBuilder::HouseBuilder(): m_pHouseBuilding(new Building())
{// ...
}void HouseBuilder::BuildBasement()
{m_pHouseBuilding->SetBasement("╬╬╬╬╬╬╬╬╬╬╬╬");
}void HouseBuilder::BuildWall()
{m_pHouseBuilding->SetWall("|田|田|田|田|");
}void HouseBuilder::BuildRoof()
{m_pHouseBuilding->SetRoof("/◥▇▇▇▇◣");
}Building *HouseBuilder::GetBuilding()
{return m_pHouseBuilding;
}/*** @brief 多层公寓施工方**/
class ApartmentBuilder: public BaseBuilder
{
public:ApartmentBuilder();~ApartmentBuilder() = default;public:void BuildBasement() override;void BuildWall() override;void BuildRoof() override;Building* GetBuilding() override;private:Building* m_pApartmentBuilding;
};ApartmentBuilder::ApartmentBuilder(): m_pApartmentBuilding(new Building())
{// ...
}void ApartmentBuilder::BuildBasement()
{m_pApartmentBuilding->SetBasement("╚═══════════╝");
}void ApartmentBuilder::BuildWall()
{for (int i = 0; i != 8; ++i)m_pApartmentBuilding->SetWall("║□□□□□□□□□□□║");
}void ApartmentBuilder::BuildRoof()
{m_pApartmentBuilding->SetRoof("╔═══════════╗");
}Building *ApartmentBuilder::GetBuilding()
{return m_pApartmentBuilding;
}

工程总监类,也就是指导者

/*** @brief 工程总监类**/
class Director
{
public:Director(BaseBuilder* pBuilder);~Director() = default;public:void SetBuilder(BaseBuilder* pBuilder);Building* Direct();                      // 指导创建private:BaseBuilder* m_pBuilder;
};Director::Director(BaseBuilder* pBuilder): m_pBuilder(pBuilder)
{// ...
}void Director::SetBuilder(BaseBuilder* pBuilder)
{m_pBuilder = pBuilder;
}Building* Director::Direct()
{m_pBuilder->BuildBasement();m_pBuilder->BuildWall();m_pBuilder->BuildRoof();return m_pBuilder->GetBuilding();
}

测试函数

void ClientTest()
{BaseBuilder* pHouseBuilder = new HouseBuilder();BaseBuilder* pApartmentBuilder = new ApartmentBuilder();Director* pDirector = new Director(pHouseBuilder);Building* pHouseBuilding = pDirector->Direct();pDirector->SetBuilder(pApartmentBuilder);Building* pApartmentBuilding = pDirector->Direct();pHouseBuilding->Show();pApartmentBuilding->Show();// 释放指针内存delete pDirector;delete pHouseBuilder;delete pApartmentBuilder;delete pHouseBuilding;delete pApartmentBuilding;
}

7 思考小结

建造者模式实现了具体的建造过程与建造的产品对象的分离,将产品对象的组装细节进行隐藏,用户如果要定义一个新的产品,只需要再构造一个具体建造过程的派生类对象。建造者模式一般用于比较复杂的对象构建,因为复杂对象的构建需要专业的建造团队,建造标准的确立让产品趋向多样化,其建造工艺可以交给多位建造者去各显其长,而建造工序则交由工程总监去全局把控,把"变"与"不变"分开,使"工艺多样化"和"工序标准化",最终实现通过相同的构建过程生产出不同产品,这也是建造者模式要达成的目标。


文章转载自:

http://ZUdK2Awe.myrmm.cn
http://MnmwGStf.myrmm.cn
http://jkuRSDt0.myrmm.cn
http://Lc0MbNsH.myrmm.cn
http://e307lxdI.myrmm.cn
http://bYmy1JgV.myrmm.cn
http://eai8cq1X.myrmm.cn
http://UaVuWZMU.myrmm.cn
http://Ew2WIoPv.myrmm.cn
http://SuBdl7JF.myrmm.cn
http://dUlIc8wp.myrmm.cn
http://DhpWHuWH.myrmm.cn
http://77pgPRFU.myrmm.cn
http://uG4CM4ut.myrmm.cn
http://YiKnY6Pv.myrmm.cn
http://T8K5WIbD.myrmm.cn
http://sZmL1zwx.myrmm.cn
http://G3U1srhQ.myrmm.cn
http://0SDCsLud.myrmm.cn
http://n4o3GnXA.myrmm.cn
http://JjBM5P55.myrmm.cn
http://jLyezF4N.myrmm.cn
http://8sD7iUTY.myrmm.cn
http://miLNf4hD.myrmm.cn
http://vxX3Pw7O.myrmm.cn
http://nmshz1WD.myrmm.cn
http://4ndJoeS0.myrmm.cn
http://hXPc0RS4.myrmm.cn
http://GEKrLGOI.myrmm.cn
http://QRNqL0jn.myrmm.cn
http://www.dtcms.com/a/386173.html

相关文章:

  • 到底什么是智能网联汽车??第二期——决策与控制
  • 将普通Wpf项目改成Prism项目
  • 微硕WINSOK高性能N沟道场效应管WSD3040DN56,助力汽车中控散热风扇静音长寿命
  • nextjs+shadcn+tailwindcss实现博客中的overview
  • cursor-关于自定义指令的问题处理
  • Vision Transformer (ViT) :Transformer在computer vision领域的应用(四)
  • 【开题答辩全过程】以 “今天吃什么”微信小程序为例,包含答辩的问题和答案
  • iOS App 内存泄漏与性能调优实战 如何排查内存问题、优化CPU与GPU性能、降低耗电并提升流畅度(uni-app iOS开发优化指南)
  • 从 Token 拦截器到 Web 配置
  • Next.js 的原理和它的使用场景
  • SPAR模型优化思路
  • pycharm+miniconda cursor+miniconda配置
  • windows在pycharm中为项目添加已有的conda环境
  • 微信小程序实现-单选-以及全选功能。
  • 知识点19:生产环境的安全与治理
  • 软件开源协议(Open Source License)介绍
  • SAP HANA Scale-out 04:缓存
  • ios制作storyboard全屏启动图
  • 2025高教杯数学建模大赛全流程,从数据处理、建模到模型评价
  • 点拨任务应用于哪些业务场景
  • 墨色规则与血色节点:C++红黑树设计与实现探秘
  • C#语言入门详解(19)委托详解
  • 【数字展厅】企业展厅设计怎样平衡科技与人文呈现?
  • Day25_【深度学习(3)—PyTorch使用(6)—张量拼接操作】
  • WSL2(ubuntu20.04)+vscode联合开发(附迁移方法)
  • 无线数传模块优化汽车装配立库物料运送设备间低延迟通信方案
  • Parasoft助力「东软睿驰」打造高质量汽车软件
  • 设计多租户 SaaS 系统,如何做到数据隔离 资源配额?
  • 基于错误xsleak 悬空标记 使用css利用帧计数 -- Pure leak ASIS CTF 2025
  • 【Day 57】Redis的部署