Builder Pattern:中文译名为“生成器模式”、“建造模式”。
示例
假设一个对象Student:
1 | public class Student { |
初级编码
不使用builder模式,我们创建一个实例并给实例赋值是这样的:
1 | Student std = new Student(); |
使用builder模式
重新改造一下Student类:
1 | public class Student { |
使用builder模式后的画风是这个样子的:
1 | Student std = Student.builder().id(10001).age(18).name("小明").gender("male").build(); |
从此再也不用先new一个实例然后挨个赋值啦,尤其对那些属性超级多的对象,或者创建实例时有些属性是可选的,写起来更是简洁。
改造builder模式要点
- 静态内部类
- 静态内部类属性设置方法与属性名相同(建议相同)
- 静态内部类属性设置方法返回内部类实例本身
- 内部静态类需要一个build()方法且返回类型为外部类
- 外部类需要实现一个全参数和无参构造函数
- 外部类需要一个静态builder()方法且返回类型为静态内部类
Lombok
Lombok提供了@Builder声明式注解,直接可以让POJO拥有builder模式。
参考资料:
- 《Head First 设计模式》
- org.elasticsearch.common.xcontent.XContentBuilder
- J-IM消息类org.jim.common.packets.Message及子类设计(v2.6.0)
- Lombok使用与原理
更新(2019/8/3)
今天看到几篇Builder模式的博客,对之前的设计进行改进:
- 静态内部类
- 静态内部类属性设置方法与属性名相同(建议相同)
- 静态内部类属性设置方法返回内部类实例本身
- 内部静态类需要一个build()方法且返回类型为外部类
外部类需要实现一个全参数和无参构造函数- 外部类需要一个入参为内部类的构造函数
外部类需要一个静态builder()方法且返回类型为静态内部类
改进
1 | public class Student { |
使用对比
1 | // 改进前 |
讨论
当初想到用builder模式时,是在项目中有些javabean属性特别多,不想中规中矩的一行一行写setter方法。这里没有使用final修饰属性,说明这不是一个可变类,有一个public的无参构造函数,且所有的getter/setter方法都可访问,所以也可以看做是一个JavaBean。