实体类常见的设计模式
1. Set 链式编程
在实体类中实现链式调用通常是指让 setter 方法返回当前对象实例 (this
),从而允许连续调用多个 setter 方法设置属性值。这种方式可以使代码更加简洁和直观。
例如实体类为:
java
public class Person {
private String name;
private int age;
public Person setName(String name) {
this.name = name;
return this; // 返回当前实例以支持链式调用
}
public Person setAge(int age) {
this.age = age;
return this;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
使用:
java
Person person = new Person().setName("John").setAge(30);
System.out.println(person);
这种方式非常适合那些属性不是很多,或者不强制要求所有属性都必须初始化的情况。
可以使用
@Accessors(chain = true)
注解来自动启用链式调用(使用方式在后面)。
2. 构建者设计模式
当一个类有很多属性,特别是有些是可选的时候,使用传统的构造函数或链式 setter 方法可能会导致代码冗长且不易维护。构建者设计模式通过分离对象的构造过程与表示来解决这个问题,使得创建复杂对象的过程更加清晰和灵活。
例如实体类为:
java
public class Person {
private final String name;
private final int age;
// 私有构造函数,防止直接实例化
private Person(Builder builder) {
this.name = builder.name;
this.age = builder.age;
}
public static class Builder {
private String name;
private int age;
public Builder name(String name) {
this.name = name;
return this; // 返回当前 Builder 实例以支持链式调用
}
public Builder age(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(this); // 使用 Builder 中的数据创建新的 Person 实例
}
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + '}';
}
}
使用:
java
Person person = new Person.Builder()
.name("John")
.age(30)
.build();
System.out.println(person);
构建者模式特别适用于需要构建的对象具有许多可选参数的情况。它不仅提高了代码的可读性,也避免了构造函数参数列表过长的问题。
可以使用
@Builder
注解可以轻松实现构建者模式(使用方式在后面)。
3. 其它
3.1 两者与 Lombok 一同使用的问题
Lombok 是一个非常流行的 Java 库,它通过注解来减少样板代码,例如 getter、setter、构造函数等。然而,当你在同一个类中同时使用 Lombok 注解与手动实现的 Set 链式编程或构建者设计模式时,可能会遇到一些问题或冲突。
-
Set 链式编程与 Lombok
如果你使用 Lombok 的
@Setter
注解,并尝试手动实现链式 setter 方法,可能会出现以下问题:- 方法重复
- 不可预期的行为
为了解决这个问题,你可以选择不使用 Lombok 的
@Setter
注解,而是完全手动编写所有需要的 setter 方法,或者利用 Lombok 的@Accessors(chain = true)
注解来自动启用链式调用。例如:java@Getter @Setter @Accessors(chain = true) public class Person { private String name; private int age; }
-
构建者设计模式与 Lombok
Lombok 提供了对构建者模式的支持,通过
@Builder
注解可以轻松实现构建者模式,避免手动编写复杂的 Builder 类。但是,如果同时手动实现构建者模式和使用 Lombok 的@Builder
注解,则可能会遇到类似的问题:- 代码冗余
- 冲突
为了避免这种情况,你应该选择一种方式来实现构建者模式。如果你希望利用 Lombok 简化代码,可以删除手动编写的 Builder 实现,转而使用 Lombok 的
@Builder
注解:java@Getter @Builder public class Person { private final String name; private final int age; }
总之,在结合使用 Lombok 与自定义的 Set 链式编程或构建者设计模式时,关键是保持一致性并理解 Lombok 在背后所做的工作。通常情况下,推荐充分利用 Lombok 提供的相关注解来简化这些模式的实现,除非有特定的需求要求手动控制。这样做不仅可以减少出错的机会,还能让代码更加简洁易读。
3.2 又想方便编程、又想使用 Lombok 怎么做
-
使用
@Accessors(chain = true)
和其他 Lombok 注解当你想为你的实体类启用链式 setter 方法同时又希望自动生成
toString
、equals
和hashCode
方法时,你可以这样做:java@Getter @Setter @Accessors(chain = true) @ToString @EqualsAndHashCode public class Person { private String name; private int age; }
在这个例子中,
@Getter
和@Setter
自动生成所有属性的 getter 和 setter 方法,@Accessors(chain = true)
使得 setter 方法支持链式调用。@ToString
自动生成toString
方法,而@EqualsAndHashCode
自动生成equals
和hashCode
方法。 -
使用
@Builder
和其他 Lombok 注解如果你想使用构建者模式(通过
@Builder
注解),同时还需要toString
、equals
和hashCode
方法,同样可以直接将这些注解添加到你的类上:java@Getter // 注意:通常与 @Builder 一起使用时不需要 @Setter,除非你确实需要setter方法 @Builder @ToString @EqualsAndHashCode public class Person { private String name; private int age; }
这里需要注意的是,通常当你使用
@Builder
时,你可能不会为所有字段提供 setter 方法(因为 Builder 模式本身提供了设置属性值的方法)。然而,如果你确实需要 setter 方法,你可以继续使用@Setter
注解。
3.3 总结
虽然使用了 Set 链式编程、构建者设计模式 能更方便快捷的实现一个类,但是也产生了与 Lombok 之间的冲突,导致不能直接使用类似 @Data
等注解生成一些方法,但这个问题总的来说,是可以忽略的。
毕竟鱼和熊掌不可兼得,合适的场景使用合适的方法即可。