23种设计模式-生成器(Builder)设计模式

文章目录

  • 一.什么是生成器设计模式?
  • 二.生成器模式的特点
  • 三.生成器模式的结构
  • 四.生成器模式的优缺点
  • 五.生成器模式的 C++ 实现
  • 六.生成器模式的 Java 实现
  • 七.代码解析
  • 八. 总结

类图: 生成器设计模式类图

一.什么是生成器设计模式?

生成器模式(Builder Pattern) 是一种创建型设计模式,允许我们分步骤创建复杂对象,同时提供不同的构建方法来定制对象的各个部分。生成器模式将对象的构建过程与其表示分离,使同样的构建过程可以创建不同的表示。

二.生成器模式的特点

  • 分步骤构建复杂对象:将构建过程分解为多个步骤。
  • 产品结构清晰:对每个组件的创建都有明确的逻辑。
  • 支持多样化配置:生成器可以创建不同的对象或表示。

三.生成器模式的结构

  • Builder(生成器接口):定义构建对象的步骤。
  • ConcreteBuilder(具体生成器):实现生成器接口,完成具体步骤并生成对象。
  • Director(指挥者):控制对象构建的流程和顺序。
  • Product(产品):表示最终创建的复杂对象。
    在这里插入图片描述

四.生成器模式的优缺点

  • 优点:
    • 代码清晰:分离了构造逻辑和产品类,符合单一职责原则。
    • 灵活性强:构造步骤可以灵活调整,支持多样化的产品表示。
    • 可扩展性好:可以轻松增加新的生成器,而不影响已有代码。
  • 缺点:
    • 实现较复杂:需要引入多个类(生成器、指挥者、产品)。
    • 使用场景有限:主要用于构建过程复杂的对象,对于简单对象不适用。

五.生成器模式的 C++ 实现

#include <iostream>
#include <string>
#include <memory>
using namespace std;

// 产品类
class Product {
private:
    string partA;
    string partB;
    string partC;

public:
    void SetPartA(const string& part) { partA = part; }
    void SetPartB(const string& part) { partB = part; }
    void SetPartC(const string& part) { partC = part; }

    void Show() const {
        cout << "Product built with: " << endl;
        cout << "  PartA: " << partA << endl;
        cout << "  PartB: " << partB << endl;
        cout << "  PartC: " << partC << endl;
    }
};

// 抽象生成器
class Builder {
public:
    virtual ~Builder() = default;

    virtual void BuildPartA() = 0;
    virtual void BuildPartB() = 0;
    virtual void BuildPartC() = 0;

    virtual shared_ptr<Product> GetResult() = 0;
};

// 具体生成器
class ConcreteBuilder : public Builder {
private:
    shared_ptr<Product> product;

public:
    ConcreteBuilder() { Reset(); }

    void Reset() { product = make_shared<Product>(); }

    void BuildPartA() override { product->SetPartA("Concrete PartA"); }
    void BuildPartB() override { product->SetPartB("Concrete PartB"); }
    void BuildPartC() override { product->SetPartC("Concrete PartC"); }

    shared_ptr<Product> GetResult() override {
        auto result = product;
        Reset(); // 重置生成器以备下次使用
        return result;
    }
};

// 指挥者
class Director {
private:
    Builder* builder;

public:
    void SetBuilder(Builder* b) { builder = b; }

    void ConstructMinimalProduct() {
        builder->BuildPartA();
    }

    void ConstructFullProduct() {
        builder->BuildPartA();
        builder->BuildPartB();
        builder->BuildPartC();
    }
};

// 客户端代码
int main() {
    ConcreteBuilder builder;
    Director director;

    director.SetBuilder(&builder);

    cout << "Building minimal product:" << endl;
    director.ConstructMinimalProduct();
    auto product1 = builder.GetResult();
    product1->Show();

    cout << "\nBuilding full product:" << endl;
    director.ConstructFullProduct();
    auto product2 = builder.GetResult();
    product2->Show();

    return 0;
}

六.生成器模式的 Java 实现

// 产品类
class Product {
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) { this.partA = partA; }
    public void setPartB(String partB) { this.partB = partB; }
    public void setPartC(String partC) { this.partC = partC; }

    public void show() {
        System.out.println("Product built with:");
        System.out.println("  PartA: " + partA);
        System.out.println("  PartB: " + partB);
        System.out.println("  PartC: " + partC);
    }
}

// 抽象生成器
interface Builder {
    void buildPartA();
    void buildPartB();
    void buildPartC();
    Product getResult();
}

// 具体生成器
class ConcreteBuilder implements Builder {
    private Product product;

    public ConcreteBuilder() { reset(); }

    private void reset() { product = new Product(); }

    @Override
    public void buildPartA() { product.setPartA("Concrete PartA"); }

    @Override
    public void buildPartB() { product.setPartB("Concrete PartB"); }

    @Override
    public void buildPartC() { product.setPartC("Concrete PartC"); }

    @Override
    public Product getResult() {
        Product result = product;
        reset(); // 重置生成器以备下次使用
        return result;
    }
}

// 指挥者
class Director {
    private Builder builder;

    public void setBuilder(Builder builder) { this.builder = builder; }

    public void constructMinimalProduct() {
        builder.buildPartA();
    }

    public void constructFullProduct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

// 客户端代码
public class BuilderPatternExample {
    public static void main(String[] args) {
        ConcreteBuilder builder = new ConcreteBuilder();
        Director director = new Director();

        director.setBuilder(builder);

        System.out.println("Building minimal product:");
        director.constructMinimalProduct();
        Product product1 = builder.getResult();
        product1.show();

        System.out.println("\nBuilding full product:");
        director.constructFullProduct();
        Product product2 = builder.getResult();
        product2.show();
    }
}

七.代码解析

  • 产品类(Product)
    • 包含产品的各个组成部分(PartA、PartB 和 PartC)。
    • 提供 SetPartX 方法,用于设置对应组件值。
    • 提供 Show 方法,展示产品的状态。
  • 抽象生成器(Builder)
    • 定义了构建产品的各个步骤(BuildPartA、BuildPartB、BuildPartC)。
    • 提供 GetResult 方法,返回构建完成的产品对象。
  • 具体生成器(ConcreteBuilder)
    • 实现抽象生成器接口,提供具体的构建逻辑。
    • 包括一个 Reset 方法,用于每次构建完成后重置状态
  • 指挥者(Director):
    • 控制构建流程,按照特定顺序调用生成器的方法。
    • 提供 ConstructMinimalProduct 和 ConstructFullProduct 方法,分别展示构建简单和完整产品的流程。
  • 客户端代码
    • 创建 ConcreteBuilder 和 Director 对象。
    • 指挥者调用生成器的方法,完成产品构建。
    • 构建完成后,通过 GetResult 获取最终的产品对象,并调用 Show 方法展示产品。

八. 总结

 生成器模式通过分步骤构建复杂对象,解决了构造函数参数过多或对象构建逻辑复杂的问题。它将对象的构造过程与表示分离,使得同样的构造过程可以生成不同的产品。在实现时需要注意保持生成器的灵活性,同时避免产品类与生成器之间的强耦合。
应用场景:

  • 创建复杂对象:对象的构造涉及多个步骤或多个组成部分。
  • 代码复用:将对象的构建逻辑集中到生成器中,避免重复代码。
  • 灵活构建:构建相同类型的对象时,可以通过不同的生成器创建不同的表示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924233.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIP——堆叠技术实验配置

目录 一、堆叠的理论知识 二、堆叠技术实验配置 三、总结 一、堆叠的理论知识 1.1堆叠概述&#xff1a; 是指将两台交换机通过堆叠线缆连接在一起&#xff0c;从逻辑上变成一台交换设备&#xff0c;作为一个整体参与数据的转发。 1.2堆叠的基本概念 堆叠系统中所有的单台…

Python - 函数(四)

函数&#xff1a;在编写程序的过程中&#xff0c;有某一功能代码块出现多次&#xff0c; 但是为了提高编写的效率以及代码的重用&#xff0c;所以把具有独立功能的代码块组织为一个小模块&#xff0c;这就是函数 ‌Python中的函数‌是一组被命名的可执行代码&#xff0c;用于完…

豆包MarsCode算法题:三数之和问题

问题描述 思路分析 1. 排序数组 目的: 将数组 arr 按升序排序&#xff0c;这样可以方便地使用双指针找到满足条件的三元组&#xff0c;同时避免重复的三元组被重复计算。优势: 数组有序后&#xff0c;处理两个数和 target - arr[i] 的问题可以通过双指针快速找到所有可能的组…

使用guzzlehttp异步多进程实现爬虫业务

Python和PHP核心技术共享平台 背景 小哥近来在通过动态代理池爬取一些公司需要的大文件pdf规格书的处理。遇到的难点&#xff0c;如何保证服务器CPU、连接数等正常情况下&#xff0c;多进程、异步快速处理这些业务并且保证准确。下面小哥就给看官唠嗑一下&#xff0c;我使用gu…

Chrome和edge浏览器如何为任何网站强制暗模式

前言 因为我的编辑器是黑色&#xff0c;可能是看的时间长了比较喜欢这种颜色了&#xff0c;感觉白色有些刺眼。尤其是看文章时&#xff0c;两边的空白纯白色&#xff0c;所以强迫症搜素设置了谷歌浏览器和edge如何设置成黑色。 Chrome和edge浏览器如何为任何网站强制暗模式 前…

STM32-- keil使用 -设备选择

keil-arm 在project--》manager--》pack installer&#xff0c;更新芯片包&#xff0c; 有些这里不全面&#xff0c;可以在官网下载包进行安装。 比如stm8系列在这里是没有的&#xff0c;因为他的内核是哈弗架构。还有51单片机要在keil c51里面找 keil5中找不到或没有对应的…

K8s内存溢出问题剖析:排查与解决方案

文章目录 一、背景二、排查方案&#xff1a;1. 可能是数据量超出了限制的大小&#xff0c;检查数据目录大小2. 查看是否是内存溢出2.1 排查数据量&#xff08;查看数据目录大小是否超过limit限制&#xff09;2.2 查看pod详情发现问题 三、解决过程 一、背景 做redis压测过程中…

在 Mac ARM 架构(例如 M1 或 M2 芯片)上安装 Node.js

文章目录 方法一&#xff1a;使用 Homebrew 安装 Node.js方法二&#xff1a;使用 Node Version Manager (NVM) 安装 Node.js方法三&#xff1a;从 Node.js 官方网站下载安装包注意事项 在 Mac ARM 架构&#xff08;例如 M1 或 M2 芯片&#xff09;上安装 Node.js 可以通过几种不…

pycharm2021.1汉化失败 “chinese (simplified) language pack“ was not installed

汉化报错&#xff1a;pycharm plugin “chinese (simplified) language pack” was not installed : Invalid filename returned by a server 翻译&#xff1a;pycharm 插件“中文&#xff08;简体&#xff09;语言包”未安装&#xff1a;服务器返回的文件名无效 解决&#…

Java基于 SpringBoot+Vue的口腔管理平台(附源码+lw+部署)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

图书系统小案例

目前就实现了分页查询&#xff0c;修改&#xff0c;删除功能 这个小案例练习到了很多技能&#xff0c;比如前后端交互、异步请求、三层架构思想、后端连接数据库、配置文件、基础业务crud等等 感兴趣的小伙伴可以去做一个试试 准备工作 1、使用maven构建一个web工程 打开i…

延时系统建模,整数延时与分数延时,连续传函与离散传函,Pade近似与Thiran近似,Matlab实现

连续传递函数 严格建模&#xff1a;指数形式 根据拉普拉斯变换的性质&#xff0c; [ f ( t ) ↔ F ( s ) ] ⇔ [ f ( t − t 0 ) ↔ e − s t 0 F ( s ) ] \left[ {f\left( t \right) \leftrightarrow F\left( s \right)} \right] \Leftrightarrow \left[ {f\left( {t - {t_0…

3.14MayBeSomeStack

栈指针是sp 静态数据在内存中位置不改变 码距就是相邻两个合法的数据之间的差距&#xff0c;如果为2的话&#xff0c;相邻两个合法的数据之间存在一个冗余的数据&#xff0c;这个数据肯定是出错的&#xff0c;但是无法判断是哪个合法的数产生的&#xff1b; 如果码距是3的话&…

NLP 2、机器学习简介

人生的苦难不过伏尔加河上的纤夫 —— 24.11.27 一、机器学习起源 机器学习的本质 —— 找规律 通过一定量的训练样本找到这些数据样本中所蕴含的规律 规律愈发复杂&#xff0c;机器学习就是在其中找到这些的规律&#xff0c;挖掘规律建立一个公式&#xff0c;导致对陌生的数…

springboot视频网站系统的设计与实现(代码+数据库+LW)

摘 要 使用旧方法对视频信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在视频信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。 这次开发的视频网站系统管理员功…

探索Python网页解析新纪元:requests-html库揭秘

文章目录 **探索Python网页解析新纪元&#xff1a;requests-html库揭秘**1. 背景介绍&#xff1a;为何选择requests-html&#xff1f;2. requests-html库是什么&#xff1f;3. 如何安装requests-html库&#xff1f;4. 五个简单的库函数使用方法4.1 发起HTTP请求4.2 解析HTML内容…

DataWhale—PumpkinBook(TASK05决策树)

课程开源地址及相关视频链接&#xff1a;&#xff08;当然这里也希望大家支持一下正版西瓜书和南瓜书图书&#xff0c;支持文睿、秦州等等致力于开源生态建设的大佬✿✿ヽ(▽)ノ✿&#xff09; Datawhale-学用 AI,从此开始 【吃瓜教程】《机器学习公式详解》&#xff08;南瓜…

爱尔兰杀菌剂数据分析_1

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

捉虫笔记(七)-再探谁把系统卡住了

捉虫笔记&#xff08;七&#xff09;-再探谁把系统卡住 1、内核调试 在实体物理机上&#xff0c;内核调试的第一个门槛就是如何建立调试链接。 这里我选择的建立网络连接进行内核调试。 至于如何建立网络连接后续文章再和大家分享。 2、如何分析 在上一篇文章中&#xff0c;我们…

linux(redhat8)如何安装mysql8.0之rpmtar双版本(最新版)(内网)(离线)

一.环境 系统版本&#xff1a;Red Hat 8.5.0-20 Java环境&#xff1a;build 1.8.0_181-b13 MYSQL&#xff1a;8.x版本 二、查看内核版本 #查看内核版本&#xff0c;根据内核版本下载对应的安装包 cat /proc/version 三、安装方式 一、rpm包方式 一、下载安装包 1. 登录网…