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

设计模式Java实现-建造者模式

楔子

小七在2019年的时候,就想写一个关于设计模式的专栏,但是最终却半途而废了。粗略一想,如果做完一件事要100分钟,小七用3分钟热情做的事,最少也能完成10件事情了。所以这一次,一定要把他做完,fighting!

需求背景

以以前小七做的一个政务系统为例,为了符合国标,数据库表需要设计很多字段,大概有100多个。每次new这个实体的时候,都会调用大量的set方法,关键是这100个字段基本不会变,但是他们的组合却经常变,弄得开发的小伙伴们苦不堪言,于是前辈们就重载了很多的构造方法,结果构造方法也爆炸了,导致新来的后浪们差点直接被拍死在了沙滩上。

为了简化代码,咱们这一次就定义一个Student类,里面只包含name和age。

分析设计

因为这个对象的属性很多,且组合方式很自由,如果使用经典的new-set方式,代码大概如下:

BigObject bigObject = new BigObject();
bigObject.setO1("");
bigObject.setO2("");
bigObject.setO3("");
bigObject.setO4("");
bigObject.setO5("");
bigObject.setO6("");
bigObject.setO7("");
bigObject.setO8("");
bigObject.setO9("");
bigObject.setO10("");
...
bigObject.setO100("");   

看起来并不直观。

如果每一个组合就重载一个构造方法,也会产生很多构造方法,并且语义不明,新来的小伙伴会一脸懵逼。

但是如果我们能够抽象一下产品的构建过程,具体建造者类继承自抽象建造者类,实现具体的构建逻辑。指挥者类负责调用具体建造者类的构建方法,完成产品的构建。这样就可以降低客户端代码的复杂度,提高代码的可维护性。

定义类名
产品类Student
抽象建造者类StudentBuilder
具体建造者类StudentActualBuilder
指挥者类Commander

标准建造者模式

UML图

根据分析设计,我们可以先画一个简单的UML图,后面通过UML图编码

file

模块名称

builder.demo01

模块地址

https://gitee.com/diqirenge/design-pattern/tree/master/src/main/java/com/run2code/design/creational/builder/demo01

模块描述

经典模式代码示例

代码实现

1、定义产品类

/*** 定义产品类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Student {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

2、定义抽象建造者类

/*** 定义抽象建造者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public abstract class StudentBuilder {public abstract void buildName(String name);public abstract void buildAge(int age);public abstract Student makeStudent();
}

3、定义具体建造者类

/*** 定义具体建造者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class StudentActualBuilder extends StudentBuilder {/*** 这里使用组合,将 student 组合到实现类中*/private Student student = new Student();@Overridepublic void buildName(String name) {student.setName(name);}@Overridepublic void buildAge(int age) {student.setAge(age);}@Overridepublic Student makeStudent() {return student;}
}

4、定义指挥者类

/*** 定义指挥者类* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Commander {/*** 注入StudentBuilder*/private StudentBuilder studentBuilder;public void setStudentBuilder(StudentBuilder studentBuilder) {this.studentBuilder = studentBuilder;}public Student makeStudent(String name, int age) {this.studentBuilder.buildAge(age);this.studentBuilder.buildName(name);return this.studentBuilder.makeStudent();}
}

5、测试

public class BuilderStudentBuilderTest {@Testpublic void testBuild_01() {System.out.println("==========标准建造者模式开始==========");StudentActualBuilder studentActualBuilder = new StudentActualBuilder();Commander commander = new Commander();commander.setStudentBuilder(studentActualBuilder);// 客户端使用指挥者类创建产品对象,这样可以降低客户端代码的复杂度,提高代码的可维护性。Student student = commander.makeStudent("第七人格", 18);System.out.println(student);System.out.println("==========标准建造者模式结束==========");}
}

6、测试结果

==========标准建造者模式开始==========

Student{name='第七人格', age=18}

==========标准建造者模式结束==========

实现要点

  1. 定义产品类:产品类是最终要构建的对象,包含多个属性和方法。

  2. 定义抽象建造者类:抽象建造者类定义了产品的构建过程,包括各个部分的构建方法和返回最终产品的方法。

  3. 定义具体建造者类:具体建造者类继承自抽象建造者类,实现具体的构建逻辑。

  4. 定义指挥者类:指挥者类负责调用具体建造者类的构建方法,完成产品的构建。

用过StringBuilder的我们知道,StringBuilder有个append方法,我们学着StringBuilder将上面的代码,改为链式调用。

链式调用模式

URL图

file

模块名称

builder.demo02

模块地址

https://gitee.com/diqirenge/design-pattern/tree/master/src/main/java/com/run2code/design/creational/builder/demo02

模块描述

建造者-链式调用

代码实现

/*** 链式调用建造者示例* 关注公众号【奔跑的码畜】,一起进步不迷路** @author 第七人格* @date 2023/11/20*/
public class Student02Builder {/*** 姓名*/private String name;/*** 年龄*/private int age;/*** 学生类的构造函数** @param name 的名字* @param age  年龄*/Student02Builder(String name, int age) {this.name = name;this.age = age;}/*** 构建器(本质上就是指挥者Commander)** @return {@link StudentBuilder}*/public static Student02Builder.StudentBuilder builder() {// 构造一个StudentBuilder对象return new Student02Builder.StudentBuilder();}/*** 学生构建器(相当于StudentBuilder及其实现类StudentActualBuilder)** @author 第七人格* @date 2020/12/02*/public static class StudentBuilder {private String name;private int age;public StudentBuilder() {}public Student02Builder.StudentBuilder name(String name) {this.name = name;// 返回自身(StudentBuilder),以便链式调用return this;}public Student02Builder.StudentBuilder age(int age) {this.age = age;// 返回自身(StudentBuilder),以便链式调用return this;}/*** 构建** @return {@link Student02Builder}*/public Student02Builder build() {// 构造一个Student对象,其中的属性直接从外部传入return new Student02Builder(this.name, this.age);}@Overridepublic String toString() {return "Student.StudentBuilder(name=" + this.name + ", age=" + this.age + ")";}}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

测试

@Test
public void testBuild_02() {System.out.println("==========工作中常用-建造者模式开始==========");System.out.println(Student02Builder.builder().age(18).name("第七人格").build());System.out.println("==========工作中常用-建造者模式开始==========");
}

测试结果

==========链式调用-建造者模式开始==========

Student{name='第七人格', age=18}

==========链式调用-建造者模式开始==========

实现要点

1、使用静态方法替换指挥者Commander

public static Student02Builder.StudentBuilder builder() {// 构造一个StudentBuilder对象return new Student02Builder.StudentBuilder();
}

2、使用内部类替换StudentBuilder及StudentActualBuilder

3、内部类中设置属性的时候,返回自身,以便链式调用

面对对象面对君,不负代码不负卿

相关文章:

设计模式Java实现-建造者模式

楔子 小七在2019年的时候,就想写一个关于设计模式的专栏,但是最终却半途而废了。粗略一想,如果做完一件事要100分钟,小七用3分钟热情做的事,最少也能完成10件事情了。所以这一次,一定要把他做完&#xff0…...

微博视频怎么下载无水印

在当今社交媒体时代,微博已经成为人们获取信息、分享生活的重要平台之一。许多人在浏览微博时常常遇到一个问题:如何下载微博视频而不留下烦人的水印呢?今天,我将分享一些神秘的方法,让你轻松解锁微博视频的无水印下载技巧。 第…...

为什么要梯度累积

文章目录 梯度累积什么是梯度累积如何理解理解梯度累积梯度累积的工作原理 梯度累积的数学原理梯度累积过程如何实现梯度累积 梯度累积的可视化 梯度累积 什么是梯度累积 随着深度学习模型变得越来越复杂,模型的训练通常需要更多的计算资源,特别是在训…...

知识图谱在提升大语言模型性能中的应用:减少幻觉与增强推理的综述

幻觉现象指的是模型在生成文本时可能会产生一些听起来合理但实际上并不准确或相关的输出,这主要是由于模型在训练数据中存在知识盲区所致。 为了解决这一问题,研究人员采取了多种策略,其中包括利用知识图谱作为外部信息源。知识图谱通过将信息…...

P8800 [蓝桥杯 2022 国 B] 卡牌

P8800 [蓝桥杯 2022 国 B] 卡牌 分析 “最多” -- 二分 1.二分区间(凑齐的卡牌套数): l:a[]min;r:(a[]b[])max 2.check(x): (1)for循环内: 判断x - a[i…...

MySQL商城数据表(80-84)

80商品规格值表 DROP TABLE IF EXISTS niumo_spec_items; CREATE TABLE niumo_spec_items (itemId int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL DEFAULT 0 COMMENT 店铺ID,catId int(11) NOT NULL DEFAULT 0 COMMENT 类型ID,goodsId int(11) NOT…...

使用Gitbook生成电子书

背景 《Google工程实践文档》相对原文Google’s Engineering Practices documentation ,部分内容过时了。需要更新中文版,并使用Gitbook把Markdown文件转换成对应的PDF电子书。   上一次生成PDF电子书是5年前,当时生成电子书的环境早已不在…...

设计模式之传输对象模式

在编程江湖里,有一种模式,它如同数据的“特快专递”,穿梭于系统间,保证信息的快速准确送达,它就是——传输对象模式(Data Transfer Object, DTO)。这不仅仅是数据的搬运工,更是提升系…...

Re69:读论文 LaMDA: Language Models for Dialog Applications

诸神缄默不语-个人CSDN博文目录 诸神缄默不语的论文阅读笔记和分类 论文名称:LaMDA: Language Models for Dialog Applications ArXiv网址:https://arxiv.org/abs/2201.08239 本文介绍谷歌提出的对话大模型LaMDA,主要关注对各项指标&#x…...

算法学习:二分查找

🔥 引言 在现代计算机科学与软件工程的实践中,高效数据检索是众多应用程序的核心需求之一。二分查找算法,作为解决有序序列查询问题的高效策略,凭借其对数时间复杂度的优越性能,占据着算法领域里举足轻重的地位。本篇内…...

github提交代码失败解决方案

1.打开github.push 工具 ​ 如果未安装github客户端请参考附录github 安装配置 2.设置Git的user name和email git config --global user.name "yourname" git config --global user.email "youremail" 3.生成SSH密钥 查看是否已经有了ssh密钥&#xff1…...

连锁收银系统总仓到门店库存调拨操作教程

1、进入系统后台,系统后台登录网址: 2、点击商品>门店调拨 3、选择调出仓库和调入门店 4、可选择添加商品逐个进行调拨,也可以批量导入需要调拨的商品 然后点击确定。 5、新增调拨后,系统会显示“待出库”状态 6、仓库已经准备…...

公网tcp转流

之前做过几次公网推流的尝试, 今天试了UDP推到公网, 再用TCP从公网拉下来, 发现不行, 就直接改用TCP转TCP了. 中间中转使用的python脚本, 感谢GPT提供技术支持: import socket import threadingdef tcp_receiver(port, forward_queue):"""接收TCP数据并将其放入…...

【Linux 基础 IO】文件系统

文章目录 1.初步理解文件2. fopen ( )的详解 1.初步理解文件 🐧① 打开文件: 本质是进程打开文件; 🐧②文件没有被打开的时候在哪里呢? ----- 在磁盘中; 🐧③进程可以打开很多个文件吗&#xff…...

Chrome浏览器安装React工具

一、如果网络能访问Google商店,直接安装官方插件即可 二、网络不能访问Google商店,使用安装包进行安装 1、下载react工具包 链接:https://pan.baidu.com/s/1qAeqxSafOiNV4CG3FVVtTQ 提取码:vgwj 2、chrome浏览器安装react工具…...

React常用组件分享

1、轮播组件: React Awesome Slider React Slider Carousel Component - react-awesome-slider...

JSON原生AJAX

文章目录 JSONFastjsonfastjson引入fastjson 常用APIfastjson作用常用API使用实例 ajax和json综合(重要)请求参数和响应数据都是普通字符串响应数据改为json格式请求和响应都是js数据封装到Result类和抽取到BaseController 原生AjaxAJAX的执行流程XMLHttpRequest对象使用原生的…...

Go图片列表

需求 在一个页面浏览目录下所有图片 代码 package mainimport ("net/http""fmt""io/ioutil""sort""strings""strconv""net/url" )func handleRequest(w http.ResponseWriter, r *http.Request) { de…...

1.4 初探JdbcTemplate操作

实战目的 掌握Spring框架中JdbcTemplate的使用,实现对数据库的基本操作。理解数据库连接池的工作原理及其在实际开发中的重要性。通过实际操作,加深对Spring框架中ORM(对象关系映射)的理解。 关键技术点 JdbcTemplate操作&…...

React 第二十一章 Portals

Portals 被翻译成传送门,是 React 库中的一个特性,它允许开发者将子组件渲染到父组件 DOM 层次结构之外的其他地方。 React 组件通常是在其父组件的 DOM 层次结构中渲染的,这意味着它们的输出会被插入到父组件的某个 DOM 元素中。然而&#…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上,所以报错,到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本,cu、torch、cp 的版本一定要对…...

零基础设计模式——行为型模式 - 责任链模式

第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

数据库分批入库

今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...