贫瘠之地

华北无浪漫,死海扬起帆
多少个夜晚,独自望着天

0%

对象创建与属性设置

背景

在 Spring 框架和 MVC 三层模式下,对于创建一个对象并对属性进行赋值的操作不需要复杂的设计

代码中创建的对象往往是一个 “贫血模型”,只用来充当数据的传递者

应该根据不同的类及其功能选择合适的对象创建方式

方式

set 方法

最常见的方式;创建对象后,使用 set 方法来对属性进行赋值

1
2
3
Student student = new Student();
student.setName("张三");
student.setAge(20);

有参构造

对需要赋值的属性设置为有参构造中的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Getter
public class Student {

private String name;

private String alias;

private Integer age;

public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
}

使用上使用有参构造器来创建对象

1
Student student = new Student("张三", 20);

链式赋值

将 set 方法改造,将 this 对象返回达成链式赋值的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Student {

private String name;

private String alias;

private Integer age;

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

public Student alias(String alias) {
this.alias = alias;
return this;
}

public Student age(Integer age) {
this.age = age;
return this;
}
}

创建对象和赋值操作更流畅

1
Student student = new Student().name("张三").age(20).alias("张三三");

Lombok

Lombok 的 @Accessors(chain = true, fluent = true) 注解可以生成类似的模板代码;该注解主要是对 Bean 方法(@Getter@Setter)的生成进行进一步的配置

@Accessors 的参数:

  • fluent - 为 true 时生成的 set 方法名称不会带上 set 前缀,即以变量名作为方法名
  • chain - 为 true 时生成的 set 方法会以当前对象作为返回值,达到链式赋值的效果
  • prefix - 过滤固定前缀的变量,不对所配置前缀的变量生成 set 方法

Builder

可以称为生成器设计模式

创建出一个 Builder 生成器来对对象的创建进行管理

Builder 可以对创建对象过程中的流程进行优化,减少选配参数,可以在创建前就对属性进行校验(优点就是生成器模式的优点)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Data
public class Student {

private String name;

private String alias;

private Integer age;

public static StudentBuilder builder() {
return new StudentBuilder();
}

@Getter
public static class StudentBuilder {
private String name;

private String alias;

private Integer age;

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

public StudentBuilder alias(String alias) {
this.alias = alias;
return this;
}

public StudentBuilder age(Integer age) {
this.age = age;
return this;
}

public Student build() {
// name 和 age 必须赋值
// 如果 alias 设置了,则以设置的值为准;如果没有设置则使用 name
Student student = new Student();
student.setName(Assert.notBlank(this.name));
student.setAge(Assert.notNull(this.age));
student.setAlias(Optional.ofNullable(this.alias).orElse(this.name));
return student;
}
}
}

使用 builder() 方法创建生成器,对生成器赋值后调用 build() 方法创建对象

1
2
3
4
5
Student student = Student.builder().name("张三").age(20).build();

// build 方法调用之前其实是一个 Builder 对象
StudentBuilder builder = Student.builder().name("张三").age(20);
Student student = builder.build();

Lombok

Lombok 中使用 @Builder 注解可以自动生成模板代码

总结

方式 优点 缺点
set 方法 简单直接 写法繁杂;无法从整体控制变量赋值情况
有参构造 对属性赋值进行有力约束 不灵活,如果最终对象种类多会出现多个不同参数的有参构造器,或者大而全参数的构造器
链式赋值 写法流畅 简单的优化,但是也只解决了写法繁杂的问题
Builder 功能强大可扩展 过程中会创建更多对象;实现复杂

参考

https://blog.csdn.net/weixin_45796051/article/details/121946894