文章目录
一、背景
在实际项目中,我们经常需要构造一些字段很多的 DTO、请求对象或结果对象。
一开始,最自然的写法,往往就是 new 一个对象,然后一行一行 set。
但当对象逐渐变复杂,这种写法会很快暴露问题。
这篇文章通过一个非常典型的对比,讲清楚:
为什么在复杂对象构建场景下,Builder 模式会比手动 set 更合适。
二、手动set
你一定见过这样的代码:
java
MatchResult result = new MatchResult();
result.setResumeId(resumeId);
result.setPositionId(positionId);
result.setFinalScore(finalScore);
result.setRagScore(ragScore);
result.setGraphScore(graphScore);
result.setLlmScore(llmScore);
result.setMatchedSkills(matchedSkills);
result.setMissingSkills(missingSkills);
result.setExtraSkills(extraSkills);
result.setRecommendLevel(recommendLevel);
result.setMatchGrade(matchGrade);
手动 set 写法的几个问题
- 代码冗余,可读性差
- 容易构造出"半成品对象"
- 必填字段只能靠约定
- 扩展成本高,容易漏改
三、使用builder模式
java
/**
* 匹配结果实体
*
* @author QinFeng Luo
* @date 2026/01/12
*/
@Data
// 这里使用builder注解
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MatchResult {
/**
* 简历 ID
*/
private String resumeId;
/**
* 岗位 ID
*/
private String positionId;
/**
* 综合得分(0-100)
*/
private float finalScore;
/**
* RAG 语义相似度得分(0-100)
*/
private float ragScore;
/**
* 知识图谱技能匹配得分(0-100)
*/
private float graphScore;
/**
* LLM 综合评估得分(0-100)
*/
private float llmScore;
/**
* 匹配的技能列表
*/
private List<String> matchedSkills;
/**
* 缺失的技能列表
*/
private List<String> missingSkills;
/**
* 候选人额外技能
*/
private List<String> extraSkills;
/**
* LLM 评估报告
*/
private String llmReport;
/**
* 详细评分明细
*/
private Map<String, Object> scoreDetails;
/**
* 推荐指数(1-5星)
*/
private int recommendLevel;
/**
* 匹配等级(A/B/C/D)
*/
private String matchGrade;
}
java
MatchResult result = MatchResult.builder()
.resumeId(resumeId)
.positionId(positionId)
.finalScore(finalScore)
.ragScore(ragScore)
.graphScore(graphScore)
.llmScore(llmScore)
.matchedSkills(matchedSkills)
.missingSkills(missingSkills)
.extraSkills(extraSkills)
.recommendLevel(recommendLevel)
.matchGrade(matchGrade)
.build();
四、使用builder模式的好处
1、 可读性明显更好
java
builder()
.xxx()
.yyy()
.zzz()
.build()
2、对象构建是原子操作
java
MatchResult result = MatchResult.builder()
...
.build();
要么构建成功,
要么直接失败。
不会再出现"半成品对象"。
3、对扩展更加友好
当新增字段时:
Builder 增加一个方法
旧代码不需要改
需要使用新字段的地方再补
不需要更改之前的原始代码