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

重读Java设计模式: 深入探讨建造者模式,构建复杂对象的优雅解决方案

引言

在软件开发中,有时需要构建具有复杂结构的对象,如果直接使用构造函数或者 setter 方法逐个设置对象的属性,会导致代码变得冗长、难以维护,并且容易出错。为了解决这个问题,我们可以使用建造者模式。

一、建造者模式概述

建造者模式是一种创建型设计模式,它的主要目的是将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式常用于构建具有复杂结构的对象,例如包含多个部件的对象,或者对象的构建过程需要进行多个步骤。

二、建造者模式的结构

建造者模式包含以下几个角色:

  • 产品(Product):要构建的复杂对象,它由多个部件组成。
  • 抽象建造者(Builder):定义了构建产品的抽象方法,具体建造者类将实现这些方法来构建具体的产品。
  • 具体建造者(Concrete Builder):实现了抽象建造者定义的方法,负责构建产品的各个部件,并返回构建后的产品。
  • 指挥者(Director):负责使用建造者构建产品的对象,它通常不了解具体的构建过程,只负责按照指定的步骤调用建造者的方法来构建产品。

三、建造者模式的优点

  • 分步构建:将构建过程分步进行,每一步都由具体建造者负责,可以更加精细地控制构建过程。
  • 隔离复杂性:将构建过程与产品的表示分离,使得构建过程的变化不会影响产品的表示,从而提高了系统的灵活性和可维护性。
  • 复用性:可以使用相同的构建过程来构建不同的产品,提高了代码的复用性。
  • 逐步完善:可以逐步完善构建过程,根据需求的变化灵活地调整构建过程。

四、建造者模式的应用场景

  • 需要构建的产品具有复杂的内部结构,包含多个部件。
  • 需要构建的产品的构建过程需要进行多个步骤,并且每个步骤的实现方式可能不同。
  • 需要构建的产品的属性之间存在一定的约束关系,需要按照一定的顺序来构建产品。

五、建造者模式的示例代码

我们先来看下相关 UML 图

image-20240331101403448

  • 产品角色
package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public class Car {private Wheel wheel;private SteeringWheel steeringWheel;public Wheel getWheel() {return wheel;}public void setWheel(Wheel wheel) {this.wheel = wheel;}public SteeringWheel getSteeringWheel() {return steeringWheel;}public void setSteeringWheel(SteeringWheel steeringWheel) {this.steeringWheel = steeringWheel;}@Overridepublic String toString() {return "Car{" +"wheel=" + wheel +", steeringWheel=" + steeringWheel +'}';}
}package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public interface SteeringWheel {String steeringWheel();
}package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public class XiaomiSteeringWheel implements SteeringWheel {@Overridepublic String steeringWheel() {return "小米轮毂";}
}package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public interface Wheel {String wheelType();
}package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public class XiaomiWheel implements Wheel{@Overridepublic String wheelType() {return "小米方向盘";}
}
  • 抽象构建者
package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public abstract class CarBuilder {protected Car car = new Car();public abstract CarBuilder buildWheel(Wheel wheel);public abstract CarBuilder buildSteeringWheel(SteeringWheel steeringWheel);public Car builder() {return car;}
}
  • 具体构建者
package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public class CommonCarBuilder extends CarBuilder {@Overridepublic CarBuilder buildWheel(Wheel wheel) {this.car.setWheel(wheel);return this;}@Overridepublic CarBuilder buildSteeringWheel(SteeringWheel steeringWheel) {this.car.setSteeringWheel(steeringWheel);return this;}
}
  • 指挥官
package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public interface Director<T> {T construct();
}package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description: 小米制造商*/
public class XiaoMiDirector implements Director<Car> {private CarBuilder carBuilder;public XiaoMiDirector(CarBuilder carBuilder) {this.carBuilder = carBuilder;}@Overridepublic Car construct() {carBuilder.buildWheel(new XiaomiWheel());carBuilder.buildSteeringWheel(new XiaomiSteeringWheel());return carBuilder.builder();}
}
  • 客户端
package com.markus.desgin.mode.creational.builder;/*** @Author: zhangchenglong06* @Date: 2024/3/7* @Description:*/
public class Client {public static void main(String[] args) {CarBuilder carBuilder = new CommonCarBuilder();Director<Car> director = new XiaoMiDirector(carBuilder);Car car = director.construct();System.out.println(car);}
}

六、建造者模式在 Spring 中的应用

在Spring框架中,有几个组件使用了建造者模式的思想来构建复杂对象,其中包括:

  1. RestTemplateBuilderRestTemplateBuilder是用于构建RestTemplate实例的建造者。RestTemplate是Spring提供的用于访问Restful服务的工具类,它支持各种HTTP请求方法和数据交换格式,如JSON和XML。RestTemplateBuilder提供了一系列方法来配置RestTemplate的各种属性,例如连接超时、读取超时、拦截器等,使得构建RestTemplate实例更加灵活和便捷。
  2. WebMvcConfigurerWebMvcConfigurer是Spring MVC框架中的一个接口,用于配置Web MVC的行为。在Spring Boot应用程序中,通常会创建一个实现了WebMvcConfigurer接口的配置类来自定义Web MVC的行为。通过实现WebMvcConfigurer接口,可以通过覆盖其中的方法来配置拦截器、消息转换器、视图解析器等各种组件,从而实现对Spring MVC框架的定制化。这种灵活性和可定制性正是建造者模式的优势之一。
  3. SqlSessionFactoryBean: 在Spring中使用MyBatis进行持久化操作时,通常会配置一个SqlSessionFactoryBean实例来创建SqlSessionFactory对象。SqlSessionFactory是MyBatis框架中的核心接口,用于创建SqlSession对象,通过SqlSession对象可以执行SQL语句并与数据库进行交互。SqlSessionFactoryBean提供了一系列方法来配置MyBatis的各种属性,例如数据源、类型别名、Mapper扫描等,使得创建SqlSessionFactory实例更加灵活和可配置。

这些组件在Spring框架中使用建造者模式的思想,通过提供一系列的配置方法来构建复杂的对象实例,使得对象的创建过程更加灵活和可定制。

七、设计模式百宝箱

在本节,我们开始填充我们的百宝箱:

  • 面向对象基础
    • 抽象
    • 封装
    • 多态
    • 继承
  • 面向对象原则
    • 依赖抽象,不要依赖具体类
    • 针对接口编程,不针对具体实现编程
    • 类应该对扩展开放,对修改关闭
    • 为交互对象之间的松耦合设计而努力
  • 面向对象设计模式
    • 简单工厂模式:定义了一个创建对象的接口,将创建对象的内容从客户端抽离出来
    • 抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
    • 原型模式:通过复制现有对象来创建新对象,提高代码效率和可维护性
    • 建造者模式:将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示

八、总结

建造者模式是一种创建型设计模式,通过将构建过程与产品的表示分离,使得同样的构建过程可以创建不同的表示。本文介绍了建造者模式的概念、结构、优点、应用场景,并提供了示例代码进行说明。建造者模式可以有效地解决构建复杂对象时的代码冗长、难以维护的问题,是一种值得推荐的设计模式。

相关文章:

重读Java设计模式: 深入探讨建造者模式,构建复杂对象的优雅解决方案

引言 在软件开发中&#xff0c;有时需要构建具有复杂结构的对象&#xff0c;如果直接使用构造函数或者 setter 方法逐个设置对象的属性&#xff0c;会导致代码变得冗长、难以维护&#xff0c;并且容易出错。为了解决这个问题&#xff0c;我们可以使用建造者模式。 一、建造者…...

C语言数据结构易错知识点(6)(快速排序、归并排序、计数排序)

快速排序属于交换排序&#xff0c;交换排序还有冒泡排序&#xff0c;这个太简单了&#xff0c;这里就不再讲解。 归并排序和快速排序都是采用分治法实现的排序&#xff0c;理解它们对分支思想的感悟会更深。 计数排序属于非比较排序&#xff0c;在数据集中的情况下可以考虑使…...

使用 React Router v6.22 进行导航

使用 React Router v6.22 进行导航 React Router v6.22 是 React 应用程序中最常用的路由库之一&#xff0c;提供了强大的导航功能。本文将介绍如何在 React 应用程序中使用 React Router v6.22 进行导航。 安装 React Router 首先&#xff0c;我们需要安装 React Router v6…...

单链表的插入和删除

一、插入操作 按位序插入&#xff08;带头结点&#xff09;&#xff1a; ListInsert(&L,i,e):插入操作。在表L中的第i个位置上插入指定元素e。 typedef struct LNode{ElemType data;struct LNode *next; }LNode,*LinkList;//在第i 个位置插插入元素e (带头结点) bool Li…...

全量知识系统 之“程序”详细设计 之 “絮”---开端“元素周期表”表示的一个“打地鼠”游戏

全量知识系统 之“程序”详细设计 概述-概要和纪要 序 絮&#xff08;一个极简的开场白--“全量知识系统”自我介绍&#xff09; 将整个“人生”的三个阶段 比作“幼稚园”三班 &#xff1a; 第一步【想】-- “感性”思维游戏&#xff1a;打地鼠 。学前教育-新生期&#x…...

【详细讲解WebView的使用与后退键处理】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…...

【Linux多线程】生产者消费者模型

【Linux多线程】生产者消费者模型 目录 【Linux多线程】生产者消费者模型生产者消费者模型为何要使用生产者消费者模型生产者消费者的三种关系生产者消费者模型优点基于BlockingQueue的生产者消费者模型C queue模拟阻塞队列的生产消费模型 伪唤醒情况&#xff08;多生产多消费的…...

Django屏蔽Server响应头信息

一、背景 最近我们被安全部门的漏洞扫描工具扫出了一个服务端口的漏洞。这个服务本身是一个Django启动的web服务&#xff0c;并且除了登录页面&#xff0c;其它页面或者接口都需要进行登录授权才能进行访问。 漏洞扫描信息和提示修复信息如下: 自然这些漏洞如何修复&#xff0c…...

前端对数据进行分组和计数处理

js对数组数据的处理&#xff0c;添加属性&#xff0c;合并表格数据。 let data[{id:1,group_id:111},{id:2,group_id:111},{id:3,group_id:111},{id:4,group_id:222},{id:5,group_id:222} ]let tempDatadata; tempDatatempData.reduce((arr,item)>{let findarr.find(i>i…...

synchronized 和 lock

synchronized 和 Lock 都是 Java 中用于实现线程同步的机制&#xff0c;它们都可以保证线程安全。 # synchronized 介绍与使用 synchronized 可用来修饰普通方法、静态方法和代码块&#xff0c;当一个线程访问一个被 synchronized 修饰的方法或者代码块时&#xff0c;会自动获…...

ssh 公私钥(github)

一、生成ssh公私钥 生成自定义名称的SSH公钥和私钥对&#xff0c;需要使用ssh-keygen命令&#xff0c;这是大多数Linux和Unix系统自带的标准工具。下面&#xff0c;简单展示如何使用ssh-keygen命令来生成具有自定义名称的SSH密钥对。 步骤 1: 打开终端 首先&#xff0c;打开我…...

LangChain入门:8.打造自动生成广告文案的应用程序

在这篇技术博文中,我们将探讨如何利用LangChain框架的模板管理、变量提取和检查、模型切换以及输出解析等优势,打造一个自动生成广告文案的应用程序。 LangChain框架的优势 在介绍应用程序之前,让我们先了解一下LangChain框架的几个优势: 模板管理: 在大型项目中,文案可…...

AI如何影响装饰器模式与组合模式的选择与应用

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#xff1a;设计模式深度解析&#xff1a;AI如何影响…...

【C语言环境】Sublime中运行C语言时MinGW环境的安装

要知道&#xff0c;GCC 官网提供的 GCC 编译器是无法直接安装到 Windows 平台上的&#xff0c;如果我们想在 Windows 平台使用 GCC 编译器&#xff0c;可以安装 GCC 的移植版本。 目前适用于 Windows 平台、受欢迎的 GCC 移植版主要有 2 种&#xff0c;分别为 MinGW 和 Cygwin…...

Ubuntu18.04 下Ublox F9P 实现RTK (利用CORS服务无需自建基站)

本内容参考如下连接:Ubuntu下Ublox F9P利用CORS服务无需自建基站实现RTK-CSDN博客 一、Ublox F9P 硬件模块示意图 图中展示了Ublox F9P的接口,包括串口2(`UART1`和`UART2`),USB1。需要人为通过u-center(Ublox F9P的显示软件)软件设置以下功能: Ublox通过`UART1`向PC端发送…...

springboot+vue在idea上面的使用小结

1.在mac上面删除java的jdk方法&#xff1a; sudo rm -rfjdk的路径 sudo rm -rf /Users/like/Library/Java/JavaVirtualMachines/corretto-17.0.10/Contents/Home 2.查询 Mac的jdk版本和路径&#xff1a; /usr/libexec/java_home -V 3.mac上面查询和关闭idea的网页端口&…...

MyEclipse将项目的开发环境与服务器的JDK 版本保持一致

前言 我们使用MyEclipse开发Java项目开发中&#xff0c;偶尔会遇到因项目开发环境不协调&#xff0c;导致这样那样的问题&#xff0c;在这里以把所有环境调整为JDK1.6 为例。 操作步骤 1.Window-->Preferences-->Java-->Installed JRES 修改为 1.6版本 2.Window-->…...

为BUG编程:函数重载的烦恼 char *匹配bool而不是string

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 这是一个BUG。 运行环境为linu…...

C++第十四弹---模板初阶

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、泛型编程 2、函数模板 2.1、函数模板的概念 2.2、函数模板的格式 2.3、函数模板的原理 2.4、函数模板的实例化 2.5、模板参数的匹配原则 …...

C++--内联函数

当调用一个函数时&#xff0c;程序就会跳转到该函数&#xff0c;函数执行完毕后&#xff0c;程序又返回到原来调用该函数的位置的下一句。 函数的调用也需要花时间&#xff0c;C中对于功能简单、规模小、使用频繁的函数&#xff0c;可以将其设置为内联函数。 内联函数&#xff…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...