当前位置: 首页 > 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调用中。

http://www.lryc.cn/news/421421.html

相关文章:

  • 开源免费的海报设计器vue-fabric-editor
  • 【学习笔记】Day 4 - Day 5
  • MySQL数据分析进阶(十四)保护数据库
  • 排序算法之堆排序
  • Python中的NLP宝库:探索顶级库与工具
  • springboot + springcloud + Google pubsub+ firebase
  • 时序数据库TDengine和QuestDB对比
  • Neuralink的进展与马斯克的技术愿景——从脑机接口到AI融合的未来
  • 大数据技术——实战项目:广告数仓(第四部分)
  • cmake+ninja交叉编译android下的静态库
  • Vue项目-Table添加Form表单校验
  • 【iOS】—— 事件传递链和响应者链总结
  • 【多线程】初识进程和线程
  • 1DCNN-2DResNet并行故障诊断模型
  • Java设计模式(原型模式)
  • C/C++ 知识点:typedef 关键字
  • 【Linux学习】进程间通信之 匿名管道 与 基于管道的进程池
  • 小团队如何选需求管理软件?8款顶级推荐
  • docker操作入门
  • 简单的射箭小游戏网页源码
  • Python | Leetcode Python题解之第331题验证二叉树的前序序列化
  • 0x3 “护网行动”守之道
  • 白骑士的Matlab教学高级篇 3.1 高级编程技术
  • haproxy简介与用法
  • Geoscene Pro的三维
  • 论文阅读 - Scaling Up k-Clique Densest Subgraph Detection | SIGMOD 2023
  • 前端框架(三件套)
  • MemoryCache 缓存 实用
  • Java设计模式(命令模式)
  • 什么是 CI/CD?