java中用builder模式实现实体类的创建

本文介绍了一种使用Java实现Builder模式的方法,通过一个具体的Student类示例展示了如何利用Builder模式简化对象创建过程,尤其是在需要初始化多个属性的情况下。
package com.panther.builder;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 在设计模式中对Builder模式的定义是用于构建复杂对象的一种模式,
 * 所构建的对象往往需要多步初始化或赋值才能完成。
 * 那么,在实际的开发过程中,我们哪些地方适合用到Builder模式呢?
 * 其中使用Builder模式来替代多参数构造函数是一个比较好的实践法则。
 * Created by panther.dongdong on 2015/11/16.
 */
public class Student {
    private static final Logger LOGGER = LoggerFactory.getLogger(Student.class.getName());

    private int id;
    private int age;
    private String name;
    private String sex;
    private String love;
    private String phone;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getLove() {
        return love;
    }

    public void setLove(String love) {
        this.love = love;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }


    public static Builder create() {
        return new Builder();
    }

    public Student(Builder builder) {
        this.id = builder.id;
        this.age = builder.age;
        this.name = builder.name;
        this.sex = builder.sex;
        this.love = builder.love;
        this.phone = builder.phone;
    }

    public static class Builder {

        private int id = 0;
        private int age = 0;
        private String name = null;
        private String sex = null;
        private String love = null;
        private String phone = null;

        //构建的步骤
        public Builder addId(int id) {
            this.id = id;
            return this;
        }

        public Builder addAge(int age) {
            this.age = age;
            return this;
        }

        public Builder addName(String name) {
            this.name = name;
            return this;
        }

        public Builder addSex(String sex) {
            this.sex = sex;
            return this;
        }

        public Builder addLove(String love) {
            this.love = love;
            return this;
        }

        public Builder addPhone(String phone) {
            this.phone = phone;
            return this;
        }

        public Student build() {
            return new Student(this);
        }
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", love='" + love + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }

    /**
     * 测试生成Student
     *
     * @param args
     */
    public static void main(String[] args) {
        Student student = Student.create().addAge(18).addName("panther").addLove("play")
                .addPhone("110").addSex("男").build();
        LOGGER.info("{}", student.toString());
    }
}


<think>我们参考了用户提供的引用内容,特别是引用[1]、[2]和[3]中关于实体类定义的信息。实体类配置规则主要涉及以下几个方面: 1. **基本结构**: - 实体类通常使用`class`关键字定义,如`public class Article`[^1] - 包含私有字段(属性)和公共的getter/setter方法 - 示例: ```java public class Product { private int id; private String name; private double price; // 无参构造器(必须) public Product() {} // Getter和Setter方法 public int getId() { return id; } public void setId(int id) { this.id = id; } // 其他getter/setter... } ``` 2. **字段映射规则**: - 默认情况下,实体类的字段名与JSON/数据库列名自动匹配(如`title`映射JSON的`title`字段)[^1] - 当名称不一致时,使用注解显式指定: - Java中常用`@SerializedName`(Gson)或`@JsonProperty`(Jackson)[^2] ```java @SerializedName("product_name") private String productName; ``` - C#中使用属性注解(如`[JsonProperty("product_name")]`)[^2] 3. **特殊字段处理**: - **集合类型**:可直接定义为`List<T>`、`Set<T>`等(如`List<String> tags`)[^1] - **嵌套对象**:字段类型为其他实体类(如`Order`中包含`List<Product>`) - **日期格式**:通过`@JsonFormat`指定序列化格式 ```java @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; ``` 4. **构造器要求**: - 必须有无参数的默认构造器(Jest/Jackson等库依赖此构造器实例化对象)[^1][^2] - 可额外添加带参数的构造器,但需保留无参构造器 5. **配置扩展**: - **忽略未知字段**:添加`@JsonIgnoreProperties(ignoreUnknown = true)`避免解析失败[^4] - **只读字段**:用`@JsonIgnore`标记不参与序列化的字段 ```java @JsonIgnore private transient String computedField; ``` 6. **关联系统配置**: - 在Spring Boot中,可通过`@ConfigurationProperties`将配置文件映射到实体类[^5] ```java @ConfigurationProperties(prefix = "app.system") public class SystemConfig { private String database; private String machineId; // getter/setter... } ``` - 配置文件`application.yml`示例: ```yaml app: system: database: mysql machineId: e2dfbdb2-4a0f-4e33-9a33-0a5d7da984b5 ``` 7. **多环境适配**: - 结合`@Profile`注解实现不同环境的实体配置[^5] ```java @Profile("dev") @Component public class DevConfig extends SystemConfig { ... } ``` --- ### 完整配置示例 ```java import com.google.gson.annotations.SerializedName; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class Article { private Long id; private String title; @SerializedName("tag_list") private List<String> tags; @JsonFormat(pattern = "yyyy-MM-dd") private Date publishDate; // 必须有无参构造器 public Article() {} // Getter和Setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } // 其他getter/setter... } ``` --- ### 配置规则总结 | 规则类型 | 说明 | |-------------------|----------------------------------------------------------------------| | **命名匹配** | 默认按字段名匹配,不区分大小写(如`productName`映射`productname`) | | **显式注解** | 用`@SerializedName`或`@JsonProperty`指定JSON字段名 | | **构造器要求** | 必须有无参构造器 | | **集合类型** | 直接使用`List<T>`, `Set<T>`等集合类型 | | **日期格式化** | 通过`@JsonFormat`定义日期格式 | | **忽略字段** | `@JsonIgnore`跳过字段,`@JsonIgnoreProperties`忽略整个类的未知属性 | | **配置注入** | Spring Boot中用`@ConfigurationProperties`绑定配置文件 | > 注意:不同框架(Jest/Gson, Jackson, JPA)的注解可能不同,需根据实际技术栈选择。 --- ### 相关问题 1. **如何解决实体类字段名与数据库列名不一致的问题?** (对比JPA的`@Column`与JSON库的`@SerializedName`实现差异) 2. **实体类应该放在项目的哪个包结构中更合理?** (讨论领域驱动设计(DDD)中的实体层划分) 3. **在微服务架构下,如何保持各服务间实体类的一致性?** (引入共享JAR包或Protobuf协议的设计方案) 4. **实体类与DTO(Data Transfer Object)的本质区别是什么?** (分析充血模型 vs 贫血模型的适用场景) 5. **如何自动生成实体类Builder模式代码?** (Lombok的`@Builder`注解使用指南)</think>### 实体类配置规则详解 根据引用内容,实体类配置的核心规则如下: --- #### 1. **基础结构规则** ```java public class EntityName { // 类名采用大驼峰命名 private Long id; // 基础字段 private String name; // 字符串类型 private List<String> tags; // 集合类型[^1] } ``` - **必须包含无参构造器**:`public EntityName() {}`(Jest/Jackson等库依赖此构造器实例化对象)[^1][^2] - **字段私有化**:所有属性声明为`private` - **必须实现getter/setter**:提供完整的公共访问方法 --- #### 2. **字段映射规则** ```java // 使用注解处理字段名不一致 @SerializedName("created_at") // Gson注解[^2] private Date createdAt; @JsonProperty("product_name") // Jackson注解 private String productName; ``` - **默认映射**:字段名自动匹配JSON属性名(如`title`映射JSON的`title`字段)[^1] - **显式映射**:当名称不一致时使用注解: - Gson:`@SerializedName("json_field")` - Jackson:`@JsonProperty("json_field")` - **多别名支持**: ```java @SerializedName(value = "create_time", alternate = {"createdAt", "create_date"}) private Date createTime; ``` --- #### 3. **特殊类型处理** ```java // 日期格式化 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; // 忽略字段 @JsonIgnore private transient String computedField; // 嵌套对象 private List<OrderItem> items; // 自动递归映射[^1] ``` - **日期类型**:必须用`@JsonFormat`指定格式[^2] - **忽略字段**: - `@JsonIgnore`:跳过序列化/反序列化 - `transient`关键字:仅跳过序列化 - **嵌套对象**:直接声明为成员变量(需确保嵌套类也符合实体规则)[^1] --- #### 4. **安全性与兼容性** ```java @JsonIgnoreProperties(ignoreUnknown = true) // 忽略JSON中的未知字段[^4] public class Product { ... } ``` - **防解析失败**:添加`ignoreUnknown = true`避免因JSON新增字段导致映射中断[^4] - **枚举处理**: ```java public enum Status { ACTIVE, INACTIVE } private Status status; // 自动映射字符串值 ``` --- #### 5. **配置注入(Spring Boot特例)** ```java @ConfigurationProperties(prefix = "dubbo") // 绑定配置文件 public class DubboConfig { private String reference; private int timeout; // getter/setter } ``` ```yaml # application.yml dubbo: reference: "com.example.Service" timeout: 2000 ``` - **层级绑定**:`prefix`指定配置前缀[^4][^5] - **优先级规则**:`-D参数 > Spring配置 > properties文件`[^4] --- ### 完整配置示例 ```java import com.google.gson.annotations.SerializedName; import com.fasterxml.jackson.annotation.*; @JsonIgnoreProperties(ignoreUnknown = true) public class Article { private Long id; @SerializedName("article_title") private String title; @JsonFormat(pattern = "yyyy-MM-dd") private Date publishDate; private List<String> tags; // 必须有无参构造器 public Article() {} // Getter和Setter public Long getId() { return id; } public void setId(Long id) { this.id = id; } // 其他getter/setter... } ``` > **关键原则**:实体类主要职责是存储和管理系统内部信息[^3],设计时应保持与业务对象的强关联性。 --- ### 相关问题 1. **如何解决嵌套对象在Elasticsearch中的扁平化存储问题?** (讨论`@NestedField`注解的使用场景) 2. **JPA实体与JSON映射实体的主要区别是什么?** (对比`@Entity`和`@SerializedName`注解体系) 3. **在多模块项目中如何保持实体类的全局一致性?** (共享模块(common-module)的设计实践) 4. **如何自动生成符合规则的实体类?** (Lombok + MapStruct工具链的最佳实践) 5. **实体类应该包含业务逻辑吗?** (分析领域驱动设计(DDD)中实体与值对象的边界)[^3]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值