学了这个,三歪再也不想写各种setter了

简介: 今天又来给大家吹一下逼。三歪在公司里边也看了不少的系统了,看到结构清晰、代码清晰的系统时会赞叹能写出这种代码的人是真的牛逼。看到乱七八糟的代码又不写注释的时候也会吐槽:“这写的是啥啊”

今天又来给大家吹一下逼。

三歪在公司里边也看了不少的系统了,看到结构清晰、代码清晰的系统时会赞叹能写出这种代码的人是真的牛逼。看到乱七八糟的代码又不写注释的时候也会吐槽:“这写的是啥啊”

多看别人的代码,总会有不同的发现和体会。

最近看别人项目的时候,发现会有这种写法:

MessageTask task = MessageTask.builder()
  .content("关注 Java3y 吧 >> ")
  .messageId(String.valueOf(ThreadLocalRandom.current().nextLong()))
  .taskId("3y")
  .taskName("一起来玩")
  .build();
System.out.println(task.toString());

看代码其实很容易看出它在干嘛,就是在创建MessageTask这个对象。

平时我们初学的时候,如果要创建这个对象会怎么写?一般会有两种方法:

  1. 将属性配在构造函数上,然后直接调构造器,传入参数
  2. 调用多个set方法
// 构造器传入属性
MessageTask messageTask = new MessageTask("3y", "关注 Java3y 吧 >>", 
                                          String.valueOf(ThreadLocalRandom.current().nextLong()), "一起来玩");
// 调用各种的set方法
MessageTask messageTask = new MessageTask();
messageTask.setTaskId("3y");
messageTask.setContent("关注 Java3y 吧 >>");
messageTask.setMessageId(String.valueOf(ThreadLocalRandom.current().nextLong()));
messageTask.setTaskName("一起来玩");

日常使用的话,应该是多次调用set方法比较多的(应该都是这样的吧)。

从代码层面上,构造器传参的代码是最简短的,但在现实层面上我们很难每次都可以通过构造器传参的方式去完成对象的创建(更多的时候每个对象的属性都是不一致的)。

构造器的代码看起来非常短,但阅读起来不太友好(我得去看每个参数是什么意思);

set方法写起来不太方便,如果对象的属性较多,也会有一大串的set代码。

而文章最开始的builer链式调用就很舒服,我一看这代码就知道这肯定是哪种我不知道的设计模式。

于是我一查,原来这就叫做建造者模式


怎么实现建造者模式?


建造者模式更多的是写法上的不同,从代码结构层面上其实没有很大的区别,只是看起来会更清爽一些。

那怎么实现建造者模式呢?其实也非常简单:

  • 在domain类上创建一个静态内部类 Builder,Builder拥有domain所有的属性
  • 在domain类上创建一个private的构造函数,参数为Builder类型,里边将Builder的属性赋值给domain的属性
  • 在Builder内部类创建domain属性的赋值方法,返回值是Builder
  • Builder内部类创建一个build方法,返回domain实例

下面我们来实现一下吧,首先创建一个静态内部类Builder,并且内部类Builder拥有domain的所有属性:

public class MessageTask {
    private String taskId;
    private String content;
    private String messageId;
    private String taskName;
   // 创建内部类
    public static class Builder{
        private String taskId;
        private String content;
        private String messageId;
        private String taskName;
    }
}

在domain类上创建一个private的构造函数,参数为Builder类型,里边是将Builder的属性赋值给domain的属性:

public class MessageTask {
    private String taskId;
    private String content;
    private String messageId;
    private String taskName;
   // 增加private构造函数
    private MessageTask(Builder builder) {
        this.taskId = builder.taskId;
        this.content = builder.content;
        this.messageId = builder.messageId;
        this.taskName = builder.taskName;
    }
    public static class Builder{
        private String taskId;
        private String content;
        private String messageId;
        private String taskName;
    }
}

在Builder内部类创建domain属性的赋值方法,返回值是Builder

public class MessageTask {
    private String taskId;
    private String content;
    private String messageId;
    private String taskName;
    private MessageTask(Builder builder) {
        this.taskId = builder.taskId;
        this.content = builder.content;
        this.messageId = builder.messageId;
        this.taskName = builder.taskName;
    }
    public static class Builder{
        private String taskId;
        private String content;
        private String messageId;
        private String taskName;
        // 赋值属性的方法(返回的是Builder)
        public Builder setTaskId(String taskId) {
            this.taskId = taskId;
            return this;
        }
        public Builder setContent(String content) {
            this.content = content;
            return this;
        }
        public Builder setMessageId(String messageId) {
            this.messageId = messageId;
            return this;
        }
        public Builder setTaskName(String taskName) {
            this.taskName = taskName;
            return this;
        }
    }
}

在Builder内部类创建一个builde方法,返回domain实例

public class MessageTask {
    private String taskId;
    private String content;
    private String messageId;
    private String taskName;
    private MessageTask(Builder builder) {
        this.taskId = builder.taskId;
        this.content = builder.content;
        this.messageId = builder.messageId;
        this.taskName = builder.taskName;
    }
    public static class Builder{
        private String taskId;
        private String content;
        private String messageId;
        private String taskName;
        public Builder setTaskId(String taskId) {
            this.taskId = taskId;
            return this;
        }
        public Builder setContent(String content) {
            this.content = content;
            return this;
        }
        public Builder setMessageId(String messageId) {
            this.messageId = messageId;
            return this;
        }
        public Builder setTaskName(String taskName) {
            this.taskName = taskName;
            return this;
        }
    // 创建build方法,返回实例
        public MessageTask build() {
            return new MessageTask(this);
        }
    }
}

使用方式:先创建Builder对象,然后用Builder去赋值,最后再调用build()返回真正的实例:

MessageTask.Builder builder = new MessageTask.Builder();
MessageTask task = builder.setContent("关注 Java3y 吧 >>")
  .setTaskId("3y")
  .setTaskName("一起来玩")
  .setMessageId(String.valueOf(ThreadLocalRandom.current().nextLong()))
  .build();


借助工具使用建造者模式


从使用的角度感觉是好用了,代码也清爽了。其实可以发现的是,我们都把逻辑写到了Domain类上,这写起来肯定是需要花时间的。

我第一印象是:这种这么通用的东西,肯定是有可以一键生成的方法的,于是我瞄准了Lombok

果不其然,我们如果使用了Lombok后,在类上加上一个注解@Builder就可以使用建造者模式的代码了,非常方便

@Builder
@Data
public class MessageTask {
    private String taskId;
    private String content;
    private String messageId;
    private String taskName;
}

又想了一下,IDEA这么强大,感觉IDEA也有办法去生成Builder,也果不其然:

35.jpg

做个小调查:

  • 如果你之前已经了解过了建造者模式,你在项目中有用吗?
  • 如果你看了这篇文章才了解到了建造者模式,你在以后会用吗?

我个人是看团队的代码风格的,如果原有已经是各种set去构造对象,那我就不会再修改了。如果是新写的业务,会使用建造者模式。


目录
相关文章
|
1天前
|
人工智能 自然语言处理 安全
阿里云AI数智鉴密:AI 生成内容如何拿到一张"防篡改的身份证"
隐形水印 + C2PA签名:让AI生成内容“持证上岗”。
1088 0
|
10天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
3615 3
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
22天前
|
人工智能 缓存 前端开发
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
DeepSeek Harness + DeepSeek V4 Pro 项目实战保姆级教程!手把手带你从零安装开源 AI 编程工具,开发架构图、知识讲解网站、3D 网页游戏、全栈 AI 应用 4 个项目,覆盖运行模式选择、插件安装与开发,看看能不能对标 Claude。
13349 91
DeepSeek Harness 首发实测 + 入门教程,夯爆了!梁神我错了
|
15天前
|
Web App开发 人工智能 API
16 个超火的 DeepSeek Harness 插件,大肥鱼已经落后 N 个版本了。。。
DeepSeek Harness 精选插件推荐合集,从图片识别、浏览器操控、多 Agent 协作到手机远程控制,一口气带你看完 DSH 社区热门的十几个插件,覆盖技能扩展、UI 界面增强、整活玩法三大类,让你的鲸鱼变得更强。
1870 4
|
8天前
|
人工智能 监控 测试技术
Qwen3.8-Flash 来了,100万上下文、Agent、Coding 都加强了
8月26日,通义千问发布Qwen3.8-Flash-Next:125B参数、每Token仅激活6B,原生支持26万Token、可扩展至100万上下文;Coding、Agent与工具调用能力显著增强,面向真实软件工程任务,推动大模型从“回答问题”迈向“完成工作”。
|
11天前
|
人工智能 Linux iOS开发
Ollama使用教程:Ollama官网下载、Ollama本地部署大模型(2026最新)
Ollama 是一款免费开源的本地大模型运行工具,支持在 Windows/macOS/Linux 上离线运行 Qwen、DeepSeek、Llama 等主流开源模型,数据不出本机、隐私安全。提供 OpenAI 兼容 API,命令行一键拉取/运行/管理模型,无需联网,无调用限制,是开发者与 AI 爱好者部署本地 AI 助手的理想选择。(239 字)
|
16天前
|
人工智能 Java BI
【AI】DeepSeek Harness 安装、运行、管理插件
本文介绍了如何运行DeepSeek开源的Agent框架DeepSeek Harness(dsh)。主要内容包括:使用nvm安装适配的Node版本;通过代理加速克隆GitHub源码;使用pnpm安装依赖并启动项目;配置DeepSeek API Token;安装扩展功能的插件。该框架自带Web界面,支持模型适配、文件编辑等插件化功能
2085 1