生成器设计模式(Builder Design Pattern)[论点:概念、图示、示例、框架中的应用、场景]

news2025/2/26 14:49:46

文章目录

  • 概念
  • 相关图示
  • 代码示例
  • 框架中的应用
  • 场景
    • 多个生成器(Concrete Builder):
    • 单个生成器

概念

        生成器设计模式(Builder Design Pattern)是一种创建型设计模式,用于处理具有多个属性和复杂构造过程的对象。生成器模式通过将对象的构建过程与其表示分离,使得相同的构建过程可以创建不同的表示。这有助于减少构造函数的参数个数,提高代码的可读性和可维护性。

生成器模式的核心组件包括:

  1. 产品(Product):需要创建的复杂对象。
  2. 抽象生成器(Builder):定义用于创建产品对象各个部分的接口。
  3. 具体生成器(Concrete Builder):实现抽象生成器接口,负责创建和组装产品的各个部分。
  4. 指挥者(Director):负责构建产品的过程,通常接受一个生成器对象作为参数,并使用该对象的方法来组装产品。

相关图示

在这里插入图片描述

代码示例

// 产品
class House {
    private String foundation;
    private String structure;
    private String roof;

    public void setFoundation(String foundation) {
        this.foundation = foundation;
    }

    public void setStructure(String structure) {
        this.structure = structure;
    }

    public void setRoof(String roof) {
        this.roof = roof;
    }

    public String toString() {
        return "Foundation: " + foundation + ", Structure: " + structure + ", Roof: " + roof;
    }
}

// 抽象生成器
interface HouseBuilder {
    void buildFoundation();

    void buildStructure();

    void buildRoof();

    House getHouse();
}

// 具体生成器
class ConcreteHouseBuilder implements HouseBuilder {
    private House house;

    public ConcreteHouseBuilder() {
        house = new House();
    }

    @Override
    public void buildFoundation() {
        house.setFoundation("Concrete Foundation");
    }

    @Override
    public void buildStructure() {
        house.setStructure("Concrete Structure");
    }

    @Override
    public void buildRoof() {
        house.setRoof("Concrete Roof");
    }

    @Override
    public House getHouse() {
        return house;
    }
}

// 指挥者
class HouseDirector {
    public House constructHouse(HouseBuilder builder) {
        builder.buildFoundation();
        builder.buildStructure();
        builder.buildRoof();
        return builder.getHouse();
    }
}

// 客户端
public class BuilderPatternDemo {
    public static void main(String[] args) {
        HouseBuilder builder = new ConcreteHouseBuilder();
        HouseDirector director = new HouseDirector();
        House house = director.constructHouse(builder);
        System.out.println(house);
    }
}

框架中的应用

        Spring Boot中的生成器设计模式的一个很好的例子是org.springframework.boot.web.client.RestTemplateBuilder。这个生成器类可以帮助创建和配置RestTemplate实例。使用RestTemplateBuilder可以简化和优化RestTemplate的创建过程,尤其是当有多个配置选项时。

public class RestTemplateBuilder {
	//下面展示部分相关代码
    private Duration connectTimeout;
    private Duration readTimeout;
    private ClientHttpRequestFactory requestFactory;

    public RestTemplateBuilder() {
    }

    public RestTemplateBuilder connectTimeout(Duration connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    public RestTemplateBuilder readTimeout(Duration readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    public RestTemplateBuilder requestFactory(ClientHttpRequestFactory requestFactory) {
        this.requestFactory = requestFactory;
        return this;
    }

    public RestTemplate build() {
        SimpleClientHttpRequestFactory requestFactory = this.requestFactory == null ? new SimpleClientHttpRequestFactory() : (SimpleClientHttpRequestFactory) this.requestFactory;
        
        if (this.connectTimeout != null) {
            requestFactory.setConnectTimeout((int) this.connectTimeout.toMillis());
        }
        if (this.readTimeout != null) {
            requestFactory.setReadTimeout((int) this.readTimeout.toMillis());
        }

        return new RestTemplate(requestFactory);
    }
}


场景

生成器设计模式在不同场景下可能有不同的应用方式。以下是两种典型的场景

多个生成器(Concrete Builder):

        当需要为同一产品(Product)提供不同的表示形式或构建过程时,可以使用多个生成器。每个生成器负责创建并组装产品的各个部分,但可能采用不同的配置、数据源或构建方法。

        例如,假设有一个Report类,它需要根据不同的数据源(如CSV文件、数据库等)以及不同的格式(如HTML、PDF等)生成报告。在这种情况下,可以创建多个生成器,每个生成器负责从特定的数据源中读取数据并生成特定格式的报告。

interface ReportBuilder {
    void loadDataSource();
    void buildHeader();
    void buildContent();
    void buildFooter();
    Report getReport();
}

class CSVToHtmlReportBuilder implements ReportBuilder {
    // ...实现里面对应的方法
}

class DatabaseToPdfReportBuilder implements ReportBuilder {
    // ...实现里面对应的方法
}


单个生成器

        当一个复杂对象的变化仅仅是属性值的变化,而不涉及到整体结构的变化时,只需要一个生成者。在这种情况下,生成者可以通过扩展属性和填充属性的方法来创建具有不同属性值的复杂对象。

        例如,假设我们正在构建一个汽车制造系统,系统可以生产不同颜色、轮胎类型和发动机类型的汽车。在这种情况下,我们可以使用一个汽车生成者,并通过提供不同的颜色、轮胎类型和发动机类型来创建具有不同属性的汽车。

public class Car {
    private String color;
    private String tireType;
    private String engineType;

    public void setColor(String color) {
        this.color = color;
    }

    public void setTireType(String tireType) {
        this.tireType = tireType;
    }

    public void setEngineType(String engineType) {
        this.engineType = engineType;
    }

    @Override
    public String toString() {
        return "Car{" +
                "color='" + color + '\'' +
                ", tireType='" + tireType + '\'' +
                ", engineType='" + engineType + '\'' +
                '}';
    }
}

public class CarBuilder {
    private Car car;

    public CarBuilder() {
        car = new Car();
    }

    public CarBuilder setColor(String color) {
        car.setColor(color);
        return this;
    }

    public CarBuilder setTireType(String tireType) {
        car.setTireType(tireType);
        return this;
    }

    public CarBuilder setEngineType(String engineType) {
        car.setEngineType(engineType);
        return this;
    }

    public Car build() {
        return car;
    }
}

public class Main {
    public static void main(String[] args) {
        CarBuilder carBuilder = new CarBuilder();

        Car sportsCar = carBuilder.setColor("Red")
                                   .setTireType("Sports")
                                   .setEngineType("V8")
                                   .build();

        Car familyCar = carBuilder.setColor("Blue")
                                   .setTireType("Standard")
                                   .setEngineType("V6")
                                   .build();

        System.out.println(sportsCar);
        System.out.println(familyCar);
    }
}


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux学习】信号——信号保存 | 信号处理 | 不可重入函数,volatile,SIGCHLD信号

🐱作者:一只大喵咪1201 🐱专栏:《Linux学习》 🔥格言:你只管努力,剩下的交给时间! 信号的产生以及详细讲解了,有兴趣的小伙伴可以去看看,传送门。接下来介绍…

快速尝鲜Oracle 23c免费开发者版,惊喜多多

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

hive数据仓库--Hive介绍

1 什么是HiveHive是基于Hadoop的⼀个数据仓库⼯具,⽤来进⾏数据提取、转化、加载,这是⼀种可以存储、查询和分析存储在Hadoop中的⼤规模数据的机制。Hive数据仓库⼯具能将结构化的数据⽂件映射为⼀张数据库表,并提供类SQL的查询功能&#xff…

spring(七):事务操作

spring(七):事务操作前言一、什么是事务二、事务四个特性(ACID)三、事务操作(搭建事务操作环境)四、事务操作(Spring 事务管理介绍)五、事务操作(注解声明式事…

SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】

文章目录前言1、分布式情况下如何加锁2、具体实现过程3、测试3.1 一个服务按照多个端口同时启动3.2 使用jmeter进行压测前言 上一篇实现了单体应用下如何上锁,这一篇主要说明如何在分布式场景下上锁 上一篇地址:加锁 1、分布式情况下如何加锁 需要注意的点是: 在上锁和释放…

C/C++每日一练(20230412)

目录 1. 二维数组找最值 🌟🌟 2. 排序 🌟 3. 二叉树展开为链表 🌟🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 二维…

使用ebpf 监控golang 应用

一、背景 使用ebpf 监控grpc-go的应用,grpc-go http2 client的处理点 func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error { ...... }// operateHeaders takes action on the decoded headers. f…

大数据 | Hadoop集群搭建(完全分布式)

知识目录一、前言二、配置三台虚拟机2.1 克隆三台虚拟机2.2 配置克隆的虚拟机2.3 使用Xshell连接虚拟机2.4 配置SSH免密登录三、Hadoop集群准备3.1 安装 rsync3.2 安装xsync分发脚本3.3 安装JDK和安装Hadoop3.4 配置环境变量3.5 分发四、Hadoop集群搭建4.1 修改配置文件4.2 配置…

Python数据分析案例24——基于深度学习的锂电池寿命预测

本期开始案例较为硬核起来了,适合理工科的硕士,人文社科的同学可以看前面的案例。 案例背景 这篇文章是去年就发了,刊物也印刷了,现在分享一部分代码作为案例给需要的同学。 原文链接(知网文章 C核)&…

OSPF的优化

O_ASE --- 标志域外路由信息 --- 因为域外的路由信息不可控性较强,所以,信任程度较低,我们将其优先级设置为150。 LSA --- 链路状态通告 --- OSPF协议在不同网络环境下产生的用于携带和传递不同的信息。 LSDB --- 链路状态数据库 SPF --- 最短…

【数据分析实战】基于python对Airbnb房源进行数据分析

文章目录📚引言📖数据加载以及基本观察📃缺失值观察及处理🔖缺失值观察以及可视化🔖缺失值处理📃异常值观察及处理📖数据探索💡哪个区域的房源最受欢迎?💡哪种…

基于opencv的边缘检测方法

1、梯度运算 用OpenCV的形态变换( 膨胀、腐蚀、开运算和闭运算)函数morphologyEx 梯度运算即膨胀结果-腐蚀结果: 【注意】对于二值图像来说,必须是前景图像为白色,背景为黑色,否则需要进行反二值化处理 …

Mybatis【第一个 Mybatis 程序】

目录 一、Maven 环境配置 1、配置 pom.xml 1.1、依赖的 jar包 1.2、防止资源导出失败 2、在resources下编写 Mybatis核心配置文件 二、搭建结构 1、编写mybatis工具类(utils) 2、编写实体类(pojo) 3、Mybatis 的实现&…

【Vue3实践】(六)Vue3使用vite处理环境变量、打包部署、nginx配置

文章目录1.前言2.环境变量2.1.环境变量文件(.env)2.2.环境变量变量定义与使用3.打包部署3.1.nginx配置3.2.静态站点根路径配置4.总结1.前言 由于在日常开发中会有一部分前端的开发任务,会涉及到Vue的项目的搭建、迭代、构建发布等操作,所以想系统的学习…

Linux:主机USB设备驱动简析

文章目录1. 前言2. 分析背景3. USB 总线硬件拓扑4. USB 协议栈概览4.1 Linux USB 子系统概览4.2 USB外设(如U盘)固件基础5. Linux USB 子系统初始化6. Linux USB 主机控制器(HCD) 驱动6.1 USB 主机控制器驱动初始化6.2 USB 主机控制器设备对象注册和驱动加载7. Linux USB 设备驱…

Chatgpt接入Csdn:实现自动回复、评论、点赞

背景 起初,我只是想自己弄个工具,用来处理一下大佬们的三连支持,后面我发现大家都在讨论chatgpt,于是我将自动回复和评论消息接入到了Csdn中,不知道这篇文章能不能发出来,代码的话暂时不开源,后…

【从零开始】Docker Desktop:听说你小子要玩我

前言 🍊缘由 捡起遗忘的Docker知识 由于本狗近期项目紧任务重,高强度的搬砖导致摸鱼时间下降。在上线项目时,看到运维大神一系列骚操作,dockerk8s的知识如过眼云烟,忘得干净的很。所以想重新恶补一下docker知识&…

深度学习中的卷积神经网络

博主简介 博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的&#xff0c…

OpenCV实战(17)——FAST特征点检测

OpenCV实战(17)——FAST特征点检测0. 前言1. FAST 特征点检测2. 自适应特征检测3. 完整代码小结系列链接0. 前言 Harris 算子根据两个垂直方向上的强度变化率给出了角点(或更一般地说,兴趣点)的数学定义。但使用这种定义需要计算图像导数&am…

Android 14 新 API:直接监听截屏操作,不用再观察媒体文件了~

截屏可以说是手机设备最常用的功能了,Android 系统非常重视截屏方面的体验,近几年的更新都不忘去优化这方面的体验。 从一开始仅在通知栏提醒已截屏,到 Android 11 支持在左下角生成截屏缩略图供编辑或分享,再到 Android 12 支持…