建造者模式(Builder Pattern)C++

2023-10-26

上一节:模板方法模式(Template Method Pattern) C++

文章目录

1.理论

建造者模式(Builder Pattern)是一种创建型设计模式,旨在通过逐步构建复杂对象来解决对象创建过程的灵活性和可扩展性问题。它允许你将对象的构建步骤与表示分离,以便可以使用相同的构建过程创建不同的表示。
建造者模式通常用于创建具有多个组成部分的复杂对象,或者需要进行一系列步骤才能完成的对象构建过程。该模式将对象的构建过程封装在一个单独的"建造者"类中,它负责构建对象的各个组成部分。
建造者模式的主要角色包括以下几个部分:

  1. 产品(Product):表示正在构建的复杂对象。它通常由多个部分组成,这些部分可以是对象、属性或其他组件。
  2. 抽象建造者(Builder):定义了构建产品所需的所有方法和操作。它提供了一种接口,用于在不同的具体建造者类之间进行交互。
  3. 具体建造者(Concrete Builder):实现了抽象建造者接口,负责实际构建产品的各个部分,并定义了返回最终产品的方法。
  4. 指导者(Director):负责管理建造者的构建过程。它根据特定的顺序调用建造者的方法,以确保正确地构建产品。

使用建造者模式的基本流程如下:

  1. 定义产品的类,确定产品的各个部分。
  2. 创建抽象建造者接口,定义构建产品所需的方法。
  3. 创建具体建造者类,实现抽象建造者接口。在具体建造者类中,实现构建产品各个部分的具体操作。
  4. 创建指导者类,负责协调建造者的构建过程。它根据特定的顺序调用建造者的方法来构建产品。
  5. 客户端通过实例化具体建造者和指导者类,调用指导者的构建方法来构建产品。

建造者模式的优点包括:

  • 将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
  • 可以控制产品对象的创建过程,并可以逐步构造复杂对象。
  • 提供了更好的封装性,隐藏了产品的内部细节。
  • 提高了代码的可读性和可维护性。

建造者模式在需要创建复杂对象,并希望将构建过程与表示分离的情况下非常有用。它常被用于构建各种对象,例如在创建数据库连接、配置对象、表单生成器等场景中。

2.实践

你现在是一个游戏开发人员,当你使用C++编写一个游戏角色的创建过程时,可以使用建造者模式来实现。假设你的游戏角色由以下几个组成部分:角色名称、角色类型、角色性别、角色等级。
首先,定义一个表示游戏角色的类Character,包含角色名称、角色类型、角色性别、角色等级等属性。

class Character {
private:
    std::string name;
    std::string type;
    std::string gender;
    int level;

public:
    void setName(const std::string& name) {
        this->name = name;
    }

    void setType(const std::string& type) {
        this->type = type;
    }

    void setGender(const std::string& gender) {
        this->gender = gender;
    }

    void setLevel(int level) {
        this->level = level;
    }

    // Other methods...
};

接下来,创建一个抽象建造者类CharacterBuilder,定义构建游戏角色的各个部分的方法,并声明一个返回最终产品的方法。

class CharacterBuilder {
public:
    virtual void buildName() = 0;
    virtual void buildType() = 0;
    virtual void buildGender() = 0;
    virtual void buildLevel() = 0;

    virtual Character getResult() = 0;
};

然后,创建具体建造者类ConcreteCharacterBuilder,实现抽象建造者接口,并具体实现构建游戏角色各个部分的方法。

class ConcreteCharacterBuilder : public CharacterBuilder {
private:
    Character character;

public:
    void buildName() override {
        character.setName("John"); // 默认名称为"John"
    }

    void buildType() override {
        character.setType("Warrior"); // 默认角色类型为"Warrior"
    }

    void buildGender() override {
        character.setGender("Male"); // 默认性别为"Male"
    }

    void buildLevel() override {
        character.setLevel(1); // 默认等级为1
    }

    Character getResult() override {
        return character;
    }
};

最后,创建指导者类CharacterDirector,负责协调建造者的构建过程,按照特定顺序调用建造者的方法来构建游戏角色。

class CharacterDirector {
private:
    CharacterBuilder* builder;

public:
    void setBuilder(CharacterBuilder* builder) {
        this->builder = builder;
    }

    Character construct() {
        builder->buildName();
        builder->buildType();
        builder->buildGender();
        builder->buildLevel();
        return builder->getResult();
    }
};

使用示例:

int main() {
    ConcreteCharacterBuilder builder;
    CharacterDirector director;
    director.setBuilder(&builder);

    Character character = director.construct();

    // 使用构建后的角色对象
    // ...
    
    return 0;
}

通过以上示例,你可以看到建造者模式的应用。在这个例子中,游戏角色的创建过程被封装在CharacterBuilder中,通过指导者CharacterDirector按照特定顺序调用建造者的方法来构建角色.

以下是完整的代码

#include <iostream>
#include <string>

class Character {
private:
    std::string name;
    std::string type;
    std::string gender;
    int level;

public:
    void setName(const std::string& name) {
        this->name = name;
    }

    void setType(const std::string& type) {
        this->type = type;
    }

    void setGender(const std::string& gender) {
        this->gender = gender;
    }

    void setLevel(int level) {
        this->level = level;
    }

    void displayInfo() {
        std::cout << "Character Information:" << std::endl;
        std::cout << "Name: " << name << std::endl;
        std::cout << "Type: " << type << std::endl;
        std::cout << "Gender: " << gender << std::endl;
        std::cout << "Level: " << level << std::endl;
    }
};

class CharacterBuilder {
protected:
    Character character;

public:
    virtual void buildName() = 0;
    virtual void buildType() = 0;
    virtual void buildGender() = 0;
    virtual void buildLevel() = 0;

    Character getResult() {
        return character;
    }
};

class WarriorBuilder : public CharacterBuilder {
public:
    void buildName() override {
        character.setName("Warrior");
    }

    void buildType() override {
        character.setType("Warrior");
    }

    void buildGender() override {
        character.setGender("Male");
    }

    void buildLevel() override {
        character.setLevel(1);
    }
};

class MageBuilder : public CharacterBuilder {
public:
    void buildName() override {
        character.setName("Mage");
    }

    void buildType() override {
        character.setType("Mage");
    }

    void buildGender() override {
        character.setGender("Female");
    }

    void buildLevel() override {
        character.setLevel(1);
    }
};

class CharacterDirector {
private:
    CharacterBuilder* builder;

public:
    void setBuilder(CharacterBuilder* builder) {
        this->builder = builder;
    }

    Character construct() {
        builder->buildName();
        builder->buildType();
        builder->buildGender();
        builder->buildLevel();
        return builder->getResult();
    }
};

int main() {
    CharacterDirector director;

    // 创建一个战士角色
    WarriorBuilder warriorBuilder;
    director.setBuilder(&warriorBuilder);
    Character warrior = director.construct();
    warrior.displayInfo();

    std::cout << std::endl;

    // 创建一个法师角色
    MageBuilder mageBuilder;
    director.setBuilder(&mageBuilder);
    Character mage = director.construct();
    mage.displayInfo();

    return 0;
}

输出结果如下:

Character Information:
Name: Warrior
Type: Warrior
Gender: Male
Level: 1

Character Information:
Name: Mage
Type: Mage
Gender: Female
Level: 1

这个例子展示了建造者模式的使用。通过使用不同的建造者,我们可以构建具有不同属性的游戏角色,而无需直接操作复杂的构建过程。建造者模式将对象的构建过程和表示分离,使得我们可以更灵活地构建不同的对象,并且可以随时增加新的建造者类来扩展构建过程。

下一节:还没有写。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

建造者模式(Builder Pattern)C++ 的相关文章

  • 使用 CLion 进行 OpenCV Windows 设置

    我想在 Windows 上为 CLion IDE 设置 OpenCV 我尝试使用 OpenCV 3 1 和 2 4 得到相同的结果 我有 Windows 10 64 位 CLion 使用 cygwin 环境 到目前为止我做了什么 1 从Op
  • CMake 找不到请求的 Boost 库

    既然我已经浏览了其他人的解决方案几个小时 但找不到适合我的问题的正确答案 我想将我的具体问题带给您 我正在尝试使用 CMake 构建 vsomeip 为此 我之前构建了 boost 1 55 但是 我在 CMake 中收到以下错误 The
  • 您可以从基本 Win32 控制台模板应用程序中的 C#/Winrt 组件调用(不是 WinForm/abstractions/wrappers 或使用 C++/Winrt 模板)吗?)

    我有一个现有的程序 win32 x86 控制台应用程序 需要调用托管代码 来自 Net 的 C dll The dll不暴露给 COM 但可以从 C WinRT 组件调用并由 C WinRT 控制台模板应用引用 BUT即使安装了 C Win
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • C# 5 async/await 线程机制感觉不对?

    为什么让调用线程进入异步方法直到内部 等待 一旦调用异步方法就生成一个线程 这不是更干净吗 这样您就可以确定异步方法会立即返回 您不必担心在异步方法的早期阶段没有做任何昂贵的事情 我倾向于知道某个方法是否要在 我的 线程上执行代码 不管是堵
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 在 omp 并行 for 循环中使用 unique_ptr 会导致 SEG.FAULT

    采取以下代码 include
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 根据对象变量搜索对象列表

    我有一个对象列表 这些对象具有三个变量 ID 名称和值 这个列表中可能有很多对象 我需要根据ID或Name找到一个对象 并更改值 例子 class objec public string Name public int UID public
  • UI 函数在快速事件完成之前触发

    我有一个停靠在 Silverlight 应用程序中的 Web 浏览器框架 有时会在其上弹出全窗口 XAML Silverlight UI 元素 我已经或多或少修复了一个老问题 即 Web 框架的内容似乎与 Silverlight 内容不能很
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐

  • webpack生产阶段的配置

    开发 测试 生产 开发版 这是开发版本的配置 webpack config js const path require path 使用node的path模块 来构建路径 const htmlWebpackPlugin require htm
  • 如果有人问你数据库的原理,叫他看这篇文章

    一提到关系型数据库 我禁不住想 有些东西被忽视了 关系型数据库无处不在 而且种类繁多 从小巧实用的 SQLite 到强大的 Teradata 但很少有文章讲解数据库是如何工作的 你可以自己谷歌 百度一下 关系型数据库原理 看看结果多么的稀少
  • 计算机专业学生就业信息调研

    IT行业一直是国家优先发展的重点行业 也是国内外人才需求量最大的行业之一 尤其是近几年 很多跨国公司陆续在中国成立软件研发中心 为计算机专业的高层次人才提供高质量的就业机会 这给计算机科学与技术专业的毕业生提供了极好机遇 也使这一专业的报考
  • linux:ubuntu提示unable to locate package docker-engine

    参考 docker installation failed on Ubuntu 20 04 LTS Vmware Stack Overflow 说明 docker engine已经改为docker io
  • 小程序内容不符合规则

    一 本文目的 本文是针对小程序提交审核因 小程序内容不符合规范 造成审核不通过 相关问题的处理办法 问题如图所示 二 处理方案 调用微信官方内容安全接口 主要可以分为3种情况 视自身情况而定 详细如下 三 方案详细说明 3 1 情况一 校验
  • robotframework接口自动化常见问题七

    1 接口自动化运行报错 string indices must be integers not str 错误代码如下 原因 数据类型不匹配导致 此时的变量 reponsecon 为str类型 需要转换成json dict类型 解决方法 参考
  • 使用Go自己动手搭建一个HTTP代理服务器

    代理服务器的工作方式如下 客户端向代理服务器发送请求 表明自己需要请求的网站内容 代理服务器接收到来自客户端的请求之后 通过解析 获取到需要访问的web服务 代理服务器将客户端的请求信息全部转发给web服务器 web服务器返回响应消息给代理
  • SpringCloud搭建分布式服务架构(通俗易懂,步骤清晰)

    SpringCloud搭建分布式服务架构 问题引入 什么是SpringCloud 在了解这个之前需要有微服务的概念 基于springBoot的一套实现微服务的框架 提供了微服务所需的配置管理 基于Http协议的restful风格 返回异步数
  • 科普篇

    开发者是开源社区生生不息的源动力 为了汇聚开发者力量 共建开源生态 FISCO BCOS智能合约编译技术专项兴趣小组 Compiling Technology of Smart Contract Special Interest Group
  • 世界排名第一的永久免费开源ERP:Odoo生产制造管理功能概述

    本文节选自Odoo亚太金牌服务机构 开源智造 所编写的 ERP真的免费不花钱 Odoo应用指南 如需获取完整的知识内容 请至开源智造官网免费获取 感谢网友一键三连 点赞 转发 收藏 您的支持是我们最大的前进动力 疫情当下 辛苦钱时代 管理是
  • 利用selenium自动化库实现电影网站的数据获取

    文章目录 简单概述 任务目标 任务目标解析 技术选型与爬取 如何爬取 抓取主函数 列表页内容抓取 详情页内容抓取 如何解析 解析索引页 解析详情页 如何存储 源代码 版权信息 简单概述 本系列可能是一个比较长的系列 主要是对 Python3
  • sql server注释快捷键

    注释快捷键 先按Ctrl K 在按Ctrl C 取消注释 先按Ctrl K 在按Ctrl U
  • (附源码)ssm基于javaweb的医疗健康知识管理系统设计与实现 毕业设计131903

    目 录 摘要 1 1 绪论 1 1 1 研究背景 1 1 2研究现状 1 1 3论文结构与章节安排 1 2 医疗健康知识管理系统分析 3 2 1 可行性分析 3 2 2 系统流程分析 3 2 2 1 数据增加流程 3 2 2 2 数据修改流
  • Git讲解以及解决问题

    Github备忘录 Git讲解 一 常见一些问题 Q1 Q2 Q3 二 介绍分支branch 现在很多编译软件对提交代码操作很友好 傻瓜式操作即可 但也会遇到一些问题 本章也会对此进行记录以及解决 除此之外 还会对Git指令具体含义以及 分
  • torch-geometric使用过程中的问题

    这次记录自己在使用torch geometric时 出现的各种问题 1 安装问题 Python 3 8 torch geometric 1 6 1 pytorch 1 6 0 pandas 1 0 5 numpy 1 18 5 这里使用的各
  • keras+resnet34实现车牌识别

    1 使用PIL和opencv生成车牌图像数据 from PIL import ImageFont Image ImageDraw import cv2 import numpy as np import os from math impor
  • SpringBoot+Vue实现大学毕业设计管理系统

    文末获取源码 开发语言 Java 使用框架 spring boot 前端技术 JavaScript Vue js css3 开发工具 IDEA MyEclipse Eclipse Visual Studio Code 数据库 MySQL 5
  • 数字图像灰度处理方法

    灰度变换 灰度变换是指根据某种目标条件按一定变换关系逐点改变源图像中每一个像素灰度值的方法 目的是为了改善画质 使图像的显示效果更加清晰 图像的灰度变换处理是图像增强处理技术中的一种非常基础 直接的空间域图像处理方法 也是图像数字化软件和图
  • 避免HashMap扩容的正确姿势

    设置HashMap的初始容量 HashMap在Java的使用中占据着很重要的地位 平时使用的时候 相信很多Java程序员都知道在定义HashMap的时候 给它设置一个初始容量 以便减少hashMap扩容 resize 带来的额外开销 比如像
  • 建造者模式(Builder Pattern)C++

    上一节 模板方法模式 Template Method Pattern C 文章目录 1 理论 2 实践 1 理论 建造者模式 Builder Pattern 是一种创建型设计模式 旨在通过逐步构建复杂对象来解决对象创建过程的灵活性和可扩展性