(本文仅适用于初学者,大牛请绕道,如有错误,欢迎指正)
正常情况下,声明一个User类,然后列出几条属性,这个时候IDE会提示说缺少初始化方法。然后就直接构建构造方法,像这样
public class User {
private final String eyes;
private final String name;
private final int age;
private final String mouth;
//构造方法
public User(String eyes, String name, int age, String mouth) {
this.eyes = eyes;
this.name = name;
this.age = age;
this.mouth = mouth;
}
}
从上面代码可以看出,虽然只有4个属性,但是构造方法的参数已经显得很累赘了,这个时候就需要用到Builder模式先来简化参数的个数。
- 在User类中建一个静态Builder类。注意,只需设置一两个属性为final类型(通常是作为唯一识别的标志)
- 具有final类型的属性添加构造方法,其他的属性为返回值为Builder类型的普通方法。
public static class UserBuilder1{
private final String name;
//其他都没有final
private String eyes;
private int age;
private String mouth;
//构造方法
public UserBuilder1(String name) {
this.name = name;
}
//返回值类型为UserBuilder1的,方法名为age的方法
public UserBuilder1 age(int age){
this.age = age;
return this;
}
public UserBuilder1 mouth(String mouth){
this.mouth = mouth;
return this;
}
public UserBuilder1 eyes(String eyes){
this.eyes = eyes;
return this;
}
}
- 此时代码1中的构造方法可以被替换为Builder类型。 再加上get方法获取属性的值
//参数这里不再是很多个单独的属性,而是对象,这也符合面向对象的逻辑
public User(UserBuilder1 userBuilder1) {
this.eyes = userBuilder1.eyes;
this.age = userBuilder1.age;
this.mouth = userBuilder1.mouth;
this.name = userBuilder1.name;
}
//加上get方法为了以后获得当前对象某个属性的值
public int getAge() {
return age;
}
public String getEyes() {
return eyes;
}
public String getMouth() {
return mouth;
}
public String getName() {
return name;
}
- 以上的步骤仅是在构造方法的参数上进行了封装,简化参数的个数。但是UserBuilder1类的最本质目的是————构建User类,并且自由地访问它的属性,如果是声明属性不创建build(),对象就无法正确创建和被访问。 所以我们在UserBuilder中声明build方法
public User build(){
User user = new User(this);
return user;
}
这里的this是UserBuilder1本身,对应的是 public User(UserBuilder1 userBuilder1)
另外如果有什么线性安全的要求,就加一些判断条件
public User build() {
//由于Builder是非线程安全的,所以如果要在Builder内部类中检查一个参数的合法性,
// 必需要在对象创建完成之后再检查
User user = new User(this);
if (user.getAge() < 0 || user.getAge() > 255) {
throw new IllegalStateException("Age out of range:" + user.getAge());//线程安全
}
return user;
}
- 建一个Main方法,体验链式调用的便利
public static void main(String[] args) {
User user = new User.UserBuilder1("LL").age(18).eyes("BLACK").mouth("red").build();
}
以下是全部代码,自行体会两者的效果
效果一(链式+Builder)
public class UserDemo {
private final String eyes;
private final String name;
private final int age;
private final String mouth;
public UserDemo(UserBuilder1 userBuilder1) {
this.eyes = userBuilder1.eyes;
this.age = userBuilder1.age;
this.mouth = userBuilder1.mouth;
this.name = userBuilder1.name;
}
public int getAge() {
return age;
}
public String getEyes() {
return eyes;
}
public String getMouth() {
return mouth;
}
public String getName() {
return name;
}
public static class UserBuilder1{
private final String name;
//其他都没有final
private String eyes;
private int age;
private String mouth;
//构造方法
public UserBuilder1(String name) {
this.name = name;
}
//返回值类型为UserBuilder1的,名称的age的方法
public UserBuilder1 age(int age){
this.age = age;
return this;
}
public UserBuilder1 mouth(String mouth){
this.mouth = mouth;
return this;
}
public UserBuilder1 eyes(String eyes){
this.eyes = eyes;
return this;
}
public UserDemo build(){
UserDemo userDemo = new UserDemo(this);
return userDemo;
}
}
public static void main(String[] args) {
UserDemo user = new UserDemo.UserBuilder1("LL").age(18).eyes("BLACK").mouth("red").build();
}
}
效果二(没有链式)
public class UserDemo2 {
private final String eyes;
private final String name;
private final int age;
private final String mouth;
public UserDemo2(String eyes, String name, int age, String mouth) {
this.eyes = eyes;
this.name = name;
this.age = age;
this.mouth = mouth;
}
public int getAge() {
return age;
}
public String getEyes() {
return eyes;
}
public String getMouth() {
return mouth;
}
public String getName() {
return name;
}
public static void main(String[] args) {
//UserDemo2 user = new UserBuilder1("LL").age(18).eyes("BLACK").mouth("red").build();
UserDemo2 userDemo2 = new UserDemo2("BLACK","LL",18,"red");
System.out.println(userDemo2.getAge());
}
}