介绍
前段时间写了个项目,一个类的属性那叫一个多啊。刚开始直接写一堆set代码,后来set代码实在是太多了,真心看不下去了,用建造者模式重构了一下,嗯,看起来舒服多了。基本上很多框架中都用到了建造者模式,每个Java程序员也肯定用过建造者模式,只不过你没有意识到这就是建造者模式。
就像你用Collections.sort(List,Comparator)和Arrays.sort(Object[],Comparator)的时候是否意识这就是策略模式的典型实现,通过传入不同的比较器来达到不同的效果。
改造过程
先来演示一下我改造的过程,用了Lombok插件,不会的可以百度一下。
原来的实现
@Data
public class Student {
private String name;
private int age;
private int gender;
}
测试类
public class Test {
public static void main(String[] args) {
Student student = new Student();
student.setName("小明");
student.setAge(10);
student.setGender(1);
// Student(name=小明, age=10, gender=1)
System.out.println(student);
}
}
后来的实现
@Data
@Builder
public class Student {
private String name;
private int age;
private int gender;
}
测试类
public class Test {
public static void main(String[] args) {
Student student = Student.builder().name("小明")
.age(10).gender(1).build();
// Student(name=小明, age=10, gender=1)
System.out.println(student);
}
}
全程链式调用,清晰知道每个字段的含义,而且还节省行数,不能太爽。
如何写建造者模式?
直接看最后编译生成的class文件反编译后的内容
public class Student {
private String name;
private int age;
private int gender;
Student(String name, int age, int gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
public static Student.StudentBuilder builder() {
return new Student.StudentBuilder();
}
// 省略get和set方法
public String toString() {
return "Student(name=" + this.getName() + ", age=" + this.getAge() + ", gender=" + this.getGender() + ")";
}
public static class StudentBuilder {
private String name;
private int age;
private int gender;
StudentBuilder() {
}
public Student.StudentBuilder name(String name) {
this.name = name;
return this;
}
public Student.StudentBuilder age(int age) {
this.age = age;
return this;
}
public Student.StudentBuilder gender(int gender) {
this.gender = gender;
return this;
}
public Student build() {
return new Student(this.name, this.age, this.gender);
}
}
}
我觉得我不用解释你都能看懂这个代码的意思,也就两部分。
1.生成建造者类,给建造者类赋值
恭喜你,已经看懂什么是建造者模式了。
Lombok中@Builder注解的使用
如果你的项目中可以用Lombok插件,就不用自己手写建造者类了,直接用@Builder注解即可。如果不可以,仿造上面的类写一个建造者类也是很快的。@Builder注解需要注意的地方有如下几点。
没有继承的情况
上面已经演示了
有继承的情况
1.对于父类,使用@AllArgsConstructor注解
@Data
@AllArgsConstructor
public class Person {
private int weight;
private int height;
}
@Data
@ToString(callSuper = true)
public class Student extends Person {
private String schoolName;
private String grade;
@Builder
public Student(int weight, int height, String schoolName, String grade) {
super(weight, height);
this.schoolName = schoolName;
this.grade = grade;
}
public static void main(String[] args) {
Student student = Student.builder().schoolName("清华附小").grade("二年级")
.weight(10).height(10).build();
// Student(super=Person(weight=10, height=10), schoolName=清华附小, grade=二年级)
System.out.println(student.toString());
}
}
在框架中的应用
基本上所有的Java框架都用到了建造者模式,因为链式赋值真的很爽。我Google了一点用了建造者模式的代码,方便大家理解。整体思路一样,可能具体实现略微有点差别。
Guava Cache框架
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(2)
.expireAfterWrite(3,TimeUnit.SECONDS)
.build();
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️