1.3 生成器 Builder

2023-05-16

专业描述 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。

生成器模式结构
在这里插入图片描述

  1. 生成器 (Builder) 接口声明在所有类型生成器中通用的产品构造步骤。

  2. 具体生成器 (Concrete Builders) 提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。

  3. 产品 (Products) 是最终生成的对象。 由不同生成器构造的产品无需属于同一类层次结构或接口。

  4. 主管 (Director) 类定义调用构造步骤的顺序, 这样你就可以创建和复用特定的产品配置。

  5. 客户端 (Client) 必须将某个生成器对象与主管类关联。 一般情况下, 你只需通过主管类构造函数的参数进行一次性关联即可。 此后主管类就能使用生成器对象完成后续所有的构造任务。 但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。 在这种情况下, 你在使用主管类生产产品时每次都可以使用不同的生成器。

实现方法

  1. 清晰地定义通用步骤, 确保它们可以制造所有形式的产品。 否则你将无法进一步实施该模式。

  2. 在基本生成器接口中声明这些步骤。

  3. 为每个形式的产品创建具体生成器类, 并实现其构造步骤。

  4. 不要忘记实现获取构造结果对象的方法。 你不能在生成器接口中声明该方法, 因为不同生成器构造的产品可能没有公共接口, 因此你就不知道该方法返回的对象类型。 但是, 如果所有产品都位于单一类层次中, 你就可以安全地在基本接口中添加获取生成对象的方法。

  5. 考虑创建主管类。 它可以使用同一生成器对象来封装多种构造产品的方式。

  6. 客户端代码会同时创建生成器和主管对象。 构造开始前, 客户端必须将生成器对象传递给主管对象。 通常情况下, 客户端只需调用主管类构造函数一次即可。 主管类使用生成器对象完成后续所有制造任务。 还有另一种方式, 那就是客户端可以将生成器对象直接传递给主管类的制造方法。

  7. 只有在所有产品都遵循相同接口的情况下, 构造结果可以直接通过主管类获取。 否则, 客户端应当通过生成器获取构造结果。

使用示例: 当你需要创建一个可能有许多配置选项的对象时, 该模式会特别有用。

识别方法: 生成器模式可以通过类来识别, 它拥有一个构建方法和多个配置结果对象的方法。 生成器方法通常支持方法链 (例如 someBuilder->setValueA(1)->setValueB(2)->create() )。

C++算法概念示例

/**
 * It makes sense to use the Builder pattern only when your products are quite
 * complex and require extensive configuration.
 *
 * Unlike in other creational patterns, different concrete builders can produce
 * unrelated products. In other words, results of various builders may not
 * always follow the same interface.
 */

class Product1{
    public:
    std::vector<std::string> parts_;
    void ListParts()const{
        std::cout << "Product parts: ";
        for (size_t i=0;i<parts_.size();i++){
            if(parts_[i]== parts_.back()){
                std::cout << parts_[i];
            }else{
                std::cout << parts_[i] << ", ";
            }
        }
        std::cout << "\n\n"; 
    }
};


/**
 * The Builder interface specifies methods for creating the different parts of
 * the Product objects.
 */
class Builder{
    public:
    virtual ~Builder(){}
    virtual void ProducePartA() const =0;
    virtual void ProducePartB() const =0;
    virtual void ProducePartC() const =0;
};
/**
 * The Concrete Builder classes follow the Builder interface and provide
 * specific implementations of the building steps. Your program may have several
 * variations of Builders, implemented differently.
 */
class ConcreteBuilder1 : public Builder{
    private:

    Product1* product;

    /**
     * A fresh builder instance should contain a blank product object, which is
     * used in further assembly.
     */
    public:

    ConcreteBuilder1(){
        this->Reset();
    }

    ~ConcreteBuilder1(){
        delete product;
    }

    void Reset(){
        this->product= new Product1();
    }
    /**
     * All production steps work with the same product instance.
     */

    void ProducePartA()const override{
        this->product->parts_.push_back("PartA1");
    }

    void ProducePartB()const override{
        this->product->parts_.push_back("PartB1");
    }

    void ProducePartC()const override{
        this->product->parts_.push_back("PartC1");
    }

    /**
     * Concrete Builders are supposed to provide their own methods for
     * retrieving results. That's because various types of builders may create
     * entirely different products that don't follow the same interface.
     * Therefore, such methods cannot be declared in the base Builder interface
     * (at least in a statically typed programming language). Note that PHP is a
     * dynamically typed language and this method CAN be in the base interface.
     * However, we won't declare it there for the sake of clarity.
     *
     * Usually, after returning the end result to the client, a builder instance
     * is expected to be ready to start producing another product. That's why
     * it's a usual practice to call the reset method at the end of the
     * `getProduct` method body. However, this behavior is not mandatory, and
     * you can make your builders wait for an explicit reset call from the
     * client code before disposing of the previous result.
     */

    /**
     * Please be careful here with the memory ownership. Once you call
     * GetProduct the user of this function is responsable to release this
     * memory. Here could be a better option to use smart pointers to avoid
     * memory leaks
     */

    Product1* GetProduct() {
        Product1* result= this->product;
        this->Reset();
        return result;
    }
};

/**
 * The Director is only responsible for executing the building steps in a
 * particular sequence. It is helpful when producing products according to a
 * specific order or configuration. Strictly speaking, the Director class is
 * optional, since the client can control builders directly.
 */
class Director{
    /**
     * @var Builder
     */
    private:
    Builder* builder;
    /**
     * The Director works with any builder instance that the client code passes
     * to it. This way, the client code may alter the final type of the newly
     * assembled product.
     */

    public:

    void set_builder(Builder* builder){
        this->builder=builder;
    }

    /**
     * The Director can construct several product variations using the same
     * building steps.
     */

    void BuildMinimalViableProduct(){
        this->builder->ProducePartA();
    }
    
    void BuildFullFeaturedProduct(){
        this->builder->ProducePartA();
        this->builder->ProducePartB();
        this->builder->ProducePartC();
    }
};
/**
 * The client code creates a builder object, passes it to the director and then
 * initiates the construction process. The end result is retrieved from the
 * builder object.
 */
/**
 * I used raw pointers for simplicity however you may prefer to use smart
 * pointers here
 */
void ClientCode(Director& director)
{
    ConcreteBuilder1* builder = new ConcreteBuilder1();
    director.set_builder(builder);
    std::cout << "Standard basic product:\n"; 
    director.BuildMinimalViableProduct();
    
    Product1* p= builder->GetProduct();
    p->ListParts();
    delete p;

    std::cout << "Standard full featured product:\n"; 
    director.BuildFullFeaturedProduct();

    p= builder->GetProduct();
    p->ListParts();
    delete p;

    // Remember, the Builder pattern can be used without a Director class.
    std::cout << "Custom product:\n";
    builder->ProducePartA();
    builder->ProducePartC();
    p=builder->GetProduct();
    p->ListParts();
    delete p;

    delete builder;
}

int main(){
    Director* director= new Director();
    ClientCode(*director);
    delete director;
    return 0;    
}

执行结果:

Standard basic product:
Product parts: PartA1

Standard full featured product:
Product parts: PartA1, PartB1, PartC1

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

1.3 生成器 Builder 的相关文章

  • 【开源软件】服务器状态监控通知平台

    声明 本文仅以学习交流为目的分享自己的开发成果 希望为更多人提供开发设计的思路 还请善待笔者的开发成果 有任何问题欢迎在文章下方留言或私信 也欢迎评论或私信指教 和大家共同进步 1 Server Monitor Platform 简介 开发
  • Kali Linux 操作系统安装详细步骤——基于 VMware 虚拟机

    1 Kali 操作系统简介 Kali Linux 是一个基于 Debian 的 Linux 发行版 xff0c 旨在进行高级渗透测试和安全审计 Kali Linux 包含数百种工具 xff0c 适用于各种信息安全任务 xff0c 如渗透测试
  • Kali Linux 使用远程桌面连接——xrdp&xfce

    笔者系统版本 Kali Kali Linux 2023 1 Kernel kernel 6 1 0 Desktop Xfce 4 18 1 1 前言 在 Windows 中我们会经常使用到远程桌面这样便利的工具 xff0c 让我们随时随地都
  • Kali Linux 配置动态/静态 IP

    笔者系统版本 Kali Kali Linux 2023 1 Kernel kernel 6 1 0 Desktop Xfce 4 18 1 1 Kali Linux 配置动态 IP 1 首先查看网卡接口名称 2 编辑网络接口配置文件 3 网
  • CentOS 7(2009) 升级 GCC 版本

    1 前言 CentOS 7 默认安装的 gcc 版本为 4 8 xff0c 但是很多时候都会需要用到更高版本的 gcc 来编译源码 xff0c 那么本文将会介绍如何在线升级 CentOS 的 gcc 版本 2 升级 GCC 1 安装 cen
  • mysql忘记密码解决方案及三种方式修改密码

    mysql用户分为root用户 xff08 超级管理员 xff0c 拥有所有权限 xff09 和普通用户 xff0c mysql服务器通过权限表来控制用户对数据库的访问 这些权限表存于root用户下的mysql数据库中 在使用mysql数据
  • Nginx架构基础

    1 写在前面 前面的内容我们介绍Nginx的一些的基础内容 xff0c 今天我们继续深入Nginx的介绍 xff0c 主要介绍下Nginx的架构的基础 2 Nginx的请求处理流程 Web Email以及TCP流量通过Nginx的传输层状态
  • maven配置以及设置国内镜像

    下载好maven时 xff0c 将maven包放进D盘 xff0c 创建maven文件夹 xff0c 进行解压 然后进行配置 右键 计算机 xff0c 选择 属性 xff0c 之后点击 高级系统设置 xff0c 点击 环境变量 xff0c
  • 关于Xray中代理的一些总结

    在Xray使用的时候遇到了一些代理问题 在一般的扫描中 为了出现意外情况 可能会封ip或者扫描崩掉 会用代理扫描网站 xff1a 1 第一种办法就是直接在 config yaml 中直接修改代理ip xff0c 我这里是将代理改为burp的
  • Angular:formGroup中嵌套formArray,在formArray中存放的可编辑table中的字段的动态展示

    今天做的项目中做了一个新增页面 xff0c 其中最顶级是一个formGroup表单命名为editClauseForm xff0c 里面有几个单独的字段 xff0c 还有一个嵌套的formArray xff0c 命名为clauseArr xf
  • 【Java系列-6】Java实现:有1、2、3、4这4个数字,能组成多少个互不相同且无重复数字的三位数、都是多少

    Java系列 6 Java实现 xff1a 有1 2 3 4这4个数字 xff0c 能组成多少个互不相同且无重复数字的三位数 xff1f 都是多少 xff1f 1 问题 Java实现 xff1a 有1 2 3 4这4个数字 xff0c 能组
  • 【C、C++系列-10】C语言实现:百钱买百鸡问题

    C C 43 43 系列 10 C语言实现 xff1a 百钱买百鸡问题 1 问题 百钱买百鸡问题 xff1a 我国古代数学家张丘建在 算经 一书中曾提出过著名的 百钱买百鸡 问题 该问题叙述如下 xff1a 鸡翁一 xff0c 值钱五 xf
  • Android 通知使用权

    1 创建service extends NotificationListenerService xff0c 并实现onNotificationRemoved onNotificationPosted public class Notific
  • Android 系统文件浏览器

    1 调用系统文件浏览器 Intent intent 61 new Intent Intent ACTION GET CONTENT intent setType 34 34 设置类型 xff0c 我这里是任意类型 xff0c 任意后缀的可以
  • Android 导入导出excel xls、xlsx

    1 导入依赖 implementation group 39 org apache poi 39 name 39 poi ooxml 39 version 39 3 17 39 implementation group 39 org apa
  • Android 导出PDF PdfDocument

    导出PDF 64 param view 要导出的view xff0c 如果view高度过高 xff08 超过一屏的高度 xff09 xff0c 在改view外部套一层Scrollview即可 如果要导出列表类型View 比如Listview
  • Android 获取所有短信-彩信

    1 权限 lt 读取短信 gt lt uses permission android name 61 34 android permission READ SMS 34 gt lt uses permission android name
  • Photoshop CC 2018 安装包安装教程

    Photoshop CC 2018功能特点 1 更紧密连接的 Photoshop 全新的智慧型锐利化 2 智慧型增加取样 内含 Extended 功能 Camera RAW 8 和图层支援 3 可编辑的圆角矩形 多重形状和路径选择 相机防手
  • 【原创】什么是原码、反码、补码?

    原码 反码 补码是计算机中对数字的二进制表示方法 原码 xff1a 将最高位作为符号位 xff08 0表示正 xff0c 1表示负 xff09 xff0c 其它数字位代表数值本身的绝对值的数字表示方式 反码 xff1a 如果是正数 xff0
  • snprintf中的错误,不要出现目标地址也是源地址的情况

    在使用snprintf时 xff0c 千万要注意一点 xff0c 不要出现目标地址也是源地址的情况 看如下例子 xff1a span class token macro property span class token directive

随机推荐

  • Linux下的shell进度条

    一 关于Shell Shell的作用是解释执行用户的命令 xff0c 它有两种执行命令的方式 xff1a 交互式和批处理 Shell脚本和编程语言很相似 xff0c 也有变量和流控制语句 xff0c 但Shell脚本是解释执行 xff0c
  • you-get相关使用命令

    you get i url 获取视频格式 清晰度等信息 you get o E folder url 保存路径 在当前目录的路径栏 输入cmd即可打开命令行 或者 shift 右键 用powershell打开 you get p PotPl
  • Spring Cloud从入门到放弃(四):Eureka的常用配置

    前言 Spring Cloud系列 点击查看Spring Cloud系列文章 eurka的常用配置 eureka server前缀的配置项 是否允许开启自我保护模式 xff0c 缺省 xff1a span class token boole
  • STM32之点亮LED

    学习一个新的处理器 xff0c 第一个程序肯定就是点亮LED xff0c 它可以让我们较快的 较清晰的了解到一个处理器的程序结构 xff0c 学习32也不例外 xff0c 首先第一个程序我们就来点亮LED xff0c 点亮LED程序有很多种
  • 判断两条线段是否相交

    判断两条直线是否相交有两步 xff1a 1 xff1a 快速排斥 xff08 可以筛除大部分 xff09 2 xff1a 跨立试验 xff08 下面会有所说明 xff09 现在开始解释 xff1a 第一步快速排斥 xff0c 实际上就是先判
  • 2015-2016 ACM-ICPC Pacific Northwest Regional Contest Div.2( Problem V Gears)

    题目地址 xff1a 点击打开链接 题意 xff1a 给你很多齿轮 xff0c 让你判断第一个齿轮和第n个齿轮的关系 有三种关系题目中已经给出 解题思路 xff1a 算是比较直观的一个dfs题目了 xff0c 重点是怎么样处理这个dfs 结
  • 免费馅饼(简单动态规划)

    都说天上不会掉馅饼 xff0c 但有一天gameboy正走在回家的小径上 xff0c 忽然天上掉下大把大把的馅饼 说来gameboy的人品实在是太好了 xff0c 这馅饼别处都不掉 xff0c 就掉落在他身旁的10米范围内 馅饼如果掉在了地
  • CF816B-Karen and Coffee

    B Karen and Coffee time limit per test2 5 seconds memory limit per test512 megabytes inputstandard input outputstandard
  • B. Mister B and Angle in Polygon 421.div2

    B Mister B and Angle in Polygon time limit per test 2 seconds memory limit per test 256 megabytes input standard input o
  • openwrt下安装lighttpd/webdav模块及改变安装目录

    Openwrt下安装lighttpd及Webdav模块 安装lightttpd 1 opkg update 2 opkg install lighttpd 依赖libxml库 3 修改 etc lighttpd lighttpd conf
  • Game of the Rows CodeForces - 839B

    Daenerys Targaryen has an army consisting of k groups of soldiers the i th group contains ai soldiers She wants to bring
  • ccf 交通规划

    201609 4试题名称 xff1a 交通规划时间限制 xff1a 1 0s内存限制 xff1a 256 0MB问题描述 xff1a 问题描述 G国国王来中国参观后 xff0c 被中国的高速铁路深深的震撼 xff0c 决定为自己的国家也建设
  • ccf 游戏

    试题编号 xff1a 201604 4试题名称 xff1a 游戏时间限制 xff1a 1 0s内存限制 xff1a 256 0MB问题描述 xff1a 问题描述 小明在玩一个电脑游戏 xff0c 游戏在一个 n m的方格图上进行 xff0c
  • POJ 1738

    There is an old stone game At the beginning of the game the player picks n 1 lt 61 n lt 61 50000 piles of stones in a li
  • 电池充电电路(TP4059)详解

    电池充电电路 xff08 TP4059 xff09 详解 TP4059是一款完整的单节锂离子电池充电器 xff0c 带电池正负极反接保护反接功能 xff0c 支持高达600mA的充电电流 xff0c 更稳定的电流一致性 该芯片的充电电流可以
  • 洛谷刷题记录【入门1】顺序结构

    入门1 顺序结构 题单 洛谷 https www luogu com cn training 100 problems 1 A 43 B Problem 洛谷 输入两个整数 a b xff0c 输出它们的和 xff08 a b 10 xff
  • 安装CLOVER引导器到硬盘EFI分区

    彻底脱离CLOVER引导U盘 目录 xff1a 1使用EFI TOOLS Clover 安装CLOVER引导器到EFI分区 2使用Clover v2 3k rXXXX pkg 安装CLOVER引导器到EFI分区 前言 我们的电脑里已经安装好
  • 安装配置IIS+MySQL+PHP环境的详细教程(之篇二PHP安装)

    上一篇参考安装配置IIS 43 MySQL 43 PHP环境的详细教程之篇一IIS安装 安装配置IIS 43 MySQL 43 PHP环境的详细教程 xff08 之篇二PHP安装 xff09 在Windows 云服务器中进行 PHP 配置
  • sublime text 4 license

    sublime text 4 注册license 亲测可用 BEGIN LICENSE Mifeng User Single User License EA7E span class token operator span span cla
  • 1.3 生成器 Builder

    专业描述 生成器模式是一种创建型设计模式 xff0c 使你能够分步骤创建复杂对象 该模式允许你使用相同的创建代码生成不同类型和形式的对象 生成器模式结构 生成器 xff08 Builder xff09 接口声明在所有类型生成器中通用的产品构