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

通用Builder工具类

假设有一个Java实体类定义:

public class Request {private String type;private String op;private PageInfo pageInfo;public static class PageInfo {private Integer pageNum;private Integer pageSize;}// 省略getter和setter...
}

在代码中创建这个对象,需要写以下代码:

public static void main(String[] args) {// 创建PageInfoRequest.PageInfo pageInfo = new Request.PageInfo();pageInfo.setPageNum(1);pageInfo.setPageSize(10);// 创建RequestRequest request = new Request();request.setOp("op");request.setType("type");request.setPageInfo(pageInfo);// 使用request...
}

由于对象创建与对象初始化相互分离,以上代码看起来十分冗长,每个属性都需要一条setter语句来赋值,当属性数量较多时看起来非常不优雅。另外,由于嵌套类的存在,创建最外层对象之前,必须把所有内层对象先创建完毕,实在是恶心至极。

针对以上问题,熟悉设计模式的朋友应该很快就能想到使用Builder模式改写这个类:

public class Request {private String type;private String op;private PageInfo pageInfo;private Request(String type, String op, PageInfo pageInfo) {this.type = type;this.op = op;this.pageInfo = pageInfo;}// 省略getter和setter...public static RequestBuilder builder() {return new RequestBuilder();}public static class PageInfo {private Integer pageNum;private Integer pageSize;private PageInfo(Integer pageNum, Integer pageSize) {this.pageNum = pageNum;this.pageSize = pageSize;}// 省略getter和setter...public static PageInfoBuilder builder() {return new PageInfoBuilder();}public static class PageInfoBuilder {private Integer pageNum;private Integer pageSize;public PageInfoBuilder pageNum(Integer pageNum) {this.pageNum = pageNum;return this;}public PageInfoBuilder pageSize(Integer pageSize) {this.pageSize = pageSize;return this;}public PageInfo build() {return new PageInfo(this.pageNum, this.pageSize);}}}public static class RequestBuilder {private String type;private String op;private PageInfo pageInfo;public RequestBuilder type(String type) {this.type = type;return this;}public RequestBuilder op(String op) {this.op = op;return this;}public RequestBuilder pageInfo(PageInfo pageInfo) {this.pageInfo = pageInfo;return this;}public Request build() {return new Request(this.type, this.op, this.pageInfo);}}
}

这样就能使用流畅的链式调用创建对象,看起来行云流水:

public static void main(String[] args) {Request request = Request.builder().op("op").type("type").pageInfo(Request.PageInfo.builder().pageNum(1).pageSize(10).build()).build();// 使用request...
}

但是问题来了,假设Request这个对象是一个第三方框架或类库中的类,且并没有按照Builder模式来实现,由于无法修改该类的代码,我们也只能被迫使用setter方法来创建这个对象。在这种情况下,我们还能拥有像之前一样丝滑般的体验吗?

下面介绍一个简单的小技巧解决这个问题。

通用Builder工具类

public class BuilderUtils {public static <T> T build(T obj, Consumer<T> applyFunc) {applyFunc.accept(obj);return obj;}
}

上面的工具类有一个build方法,这个方法只是在一个指定的对象obj上调用了我们传入的一个任意操作函数applyFunc。有了这个方法,就能在任意对象上实现类似Builder模式的写法。

import static byx.test.BuilderUtils.build;public static void main(String[] args) {Request request = build(new Request(), r -> {r.setOp("op");r.setType("type");r.setPageInfo(build(new Request.PageInfo(), p -> {p.setPageNum(1);p.setPageSize(10);}));});// 使用request...
}

这个方法巧妙地将对象创建与对象初始化结合在了一起。实际上这种方法比Builder模式更灵活,因为build方法传入的lambda表达式中可以执行任意操作,而不仅仅是给对象属性赋值。我们可以在其中加入任意复杂的逻辑,比如根据某些条件为对象属性赋予不同的值,或者执行初始化逻辑等。更重要的是,所有操作都包含在一个语句中,而不会打散在数不清的setter调用中。

相关文章:

通用Builder工具类

假设有一个Java实体类定义&#xff1a; public class Request {private String type;private String op;private PageInfo pageInfo;public static class PageInfo {private Integer pageNum;private Integer pageSize;}// 省略getter和setter... }在代码中创建这个对象&#…...

开源免费的海报设计器vue-fabric-editor

vue-fabric-editor 是一个基于 Vue.js 和 Fabric.js 的创新前端富文本编辑器&#xff0c;它将传统的文本输入体验与图形设计元素相结合&#xff0c;为用户提供了全新的内容创作方式。 以下是关于 vue-fabric-editor 的详细介绍&#xff1a; 一、技术特点 框架结合&#xff1a;…...

【学习笔记】Day 4 - Day 5

一、进度概述 1、新机环境配置 2、《地震勘探原理》第一章 3、对 “DL-FWI 研究方向展望” 组会的一些想法 二、详情 1、新机环境配置 配置新机环境着实耗了较多时间&#xff0c;导致理论进度推进较慢。 2、《地震勘探原理》第一章学习笔记 相关笔记在另一篇…...

MySQL数据分析进阶(十四)保护数据库

※食用指南&#xff1a;文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记&#xff0c;笔记整理比较粗糙&#xff0c;主要目的自存为主&#xff0c;记录完整的学习过程。&#xff08;图片超级多&#xff0c;慎看&#xff01;&#xff09; 【中字】SQL进阶教程 | 史上最易懂S…...

排序算法之堆排序

title: 堆排序 date: 2024-7-23 15:48:25 0800 categories: 排序算法 tags:排序算法堆排序 description: 堆排序&#xff08;Heap Sort&#xff09;是一种基于堆的排序算法&#xff0c;具有较高的效率和稳定性。 math: true 堆排序 堆排序&#xff08;Heap Sort&#xff09;是…...

Python中的NLP宝库:探索顶级库与工具

标题&#xff1a;Python中的NLP宝库&#xff1a;探索顶级库与工具 Python&#xff0c;作为人工智能和机器学习任务中的关键编程语言&#xff0c;为自然语言处理&#xff08;NLP&#xff09;提供了丰富的库和工具。这些库不仅功能强大&#xff0c;而且大多数都是开源的&#xf…...

springboot + springcloud + Google pubsub+ firebase

1.pom依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-gcp-starter</artifactId><version>1.2.6.RELEASE</version></dependency><dependency><groupId>org.springframe…...

时序数据库TDengine和QuestDB对比

QuestDB和TDengine都是高性能的时序数据库&#xff08;Time Series Database, TSDB&#xff09;&#xff0c;但它们在设计、功能、适用场景以及性能表现上各有特色。 以下是对两者的详细对比&#xff1a; 一、设计与架构 QuestDB 是一个开源的高性能SQL时序数据库&#xff0…...

Neuralink的进展与马斯克的技术愿景——从脑机接口到AI融合的未来

引言 Neuralink&#xff0c;这个由埃隆马斯克&#xff08;Elon Musk&#xff09;创立的公司&#xff0c;一直是科技界的焦点。自从其发布以来&#xff0c;Neuralink的脑机接口技术便吸引了全球的目光。最近&#xff0c;马斯克再次向公众展示了Neuralink的突破性进展&#xff0…...

大数据技术——实战项目:广告数仓(第四部分)

目录 第7章 数据仓库环境准备 7.1 数据仓库运行环境 7.1.1 Hive环境搭建 7.1.2 Yarn环境配置 7.2 数据仓库开发环境 第8章 广告数仓ODS层 8.1 广告信息表 8.2 推广平台表 8.3 产品表 8.4 广告投放表 8.5 日志服务器列表 8.6 广告监测日志表 8.7 数据装载脚本 第7章…...

cmake+ninja交叉编译android下的静态库

文章目录 cmakeninja案例背景重新安装ninja编译通过 参考 想整理一个库的cmake工程&#xff0c;他用 cmakeninja 简单了解了一下&#xff0c;是可以不依赖Android studio编译的cmake的&#xff0c;搜到了一个cmakeninja&#xff0c;参考[1] 案例 参考[1]中的代码 背景 cm…...

Vue项目-Table添加Form表单校验

一、HTML <template><div class"taskInfo"><el-form:model"generateParams":rules"formRules"ref"formRef"class"taskInfoForm"label-width"100px"><ul class"taskInfoSearch"&g…...

【iOS】—— 事件传递链和响应者链总结

事件传递链和响应者链总结 1. 事件传递链&#xff1a;事件传递链&#xff1a;传递流程&#xff1a;总结第一响应者&#xff1a; 2. 响应者链响应者链传递流程总结响应者链流程 总结&#xff1a; 之前也学习过这个内容这次在复习的时候&#xff0c;就想着写一下总结&#xff1a;…...

【多线程】初识进程和线程

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 前言 在我们之前编写的所有代码&#xff0c;都只能用上一个核心。众所周知&#xff0c;现在大多数CPU都有多个核心&#xff0c;但此时&#xff0c;无论如法优化程序&#xff0c…...

1DCNN-2DResNet并行故障诊断模型

往期精彩内容&#xff1a; Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Python轴承故障诊断入门教学-CSDN博客 Python轴承故障诊断 (13)基于故障信号特征提取的超强机器学习识别模型-CSDN博客 Python轴承故障诊断 (14)高创新故障识别模型-CSDN…...

Java设计模式(原型模式)

定义 使用原型实例指定待创建对象的类型&#xff0c;并且通过复制这个原型来创建新的对象。 角色 Prototype&#xff08;抽象原型角色&#xff09; ConcretePrototype&#xff08;具体原型角色&#xff09; Client&#xff08;客户端角色 优点 简化对象的创建过程&#xff0c…...

C/C++ 知识点:typedef 关键字

文章目录 一、typedef 关键字1、 基本用法2、常见用法2.1、为基本数据类型定义别名2.2、为结构体或联合体定义别名2.3、为指针类型定义别名2.4、为复杂模板类型定义别名 3、注意事项4、总结 前言&#xff1a; 在C&#xff08;以及C语言&#xff09;中&#xff0c;typedef 关键字…...

【Linux学习】进程间通信之 匿名管道 与 基于管道的进程池

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f351;进程间通信&#x1f42c;进程间通信目的 &#x1f4da;管道 &#x1f4d5;管道的原理&#x1f427;用fork来共享管道原…...

小团队如何选需求管理软件?8款顶级推荐

本文将分享8款适合小团队的需求管理软件&#xff1a;PingCode、Worktile、Tapd、Teambition、禅道、Asana、Jama Connect、Aha!。 在小团队中管理需求时&#xff0c;寻找合适的软件工具常常让人头疼&#xff0c;不同的需求管理软件提供各种功能&#xff0c;但哪些功能真正适合…...

docker操作入门

1.创建镜像&#xff0c;使用当前文件 docker build -t experience . 2.运行容器 docker run -d -p 8501:8501 --name my-running-app my-python-api docker run -p 8508:8508 experience docker run -p 8508:8508 -p 8509:8509 experience 3.查看容器状态 docker ps docker p…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...