一、什么是构造者模式
是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。创建者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加以抽象,通过子类继承或者重载的方式,动态的创建具有复合属性的对象
二、适用场景
隔离复杂对象的创建和使用,相同的方法,不同执行顺序,产生不同事件结果
三、主要作用
在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象,通过将多个简单对象通过⼀步步的组装构建出⼀个复杂对象的过程
四、代码实现
package com.ssm.user.designPattern.builderPattern;
public class Boy {
private String name;
private String nickName;
private Integer age;
private Integer hight;
// 构造方法私有化,不然客户端就会直接调用构造方法了
private Boy(String name, String nickName, Integer age, Integer hight) {
this.age = age;
this.name = name;
this.hight = hight;
this.nickName = nickName;
}
@Override
public String toString() {
return "Boy{" +
"name='" + name + ''' +
", nickName='" + nickName + ''' +
", age=" + age +
", hight=" + hight +
'}';
}
// 静态方法,用于生成一个 Builder,这个不一定要有,不过写这个方法是一个很好的习惯,
// 有些代码要求别人写 new User.UserBuilder().a()...build() 看上去就没那么好
public static Builder builder() {
return new Builder();
}
public static class Builder {
// 下面是和 Boy 一模一样的一堆属性
private String name;
private String nickName;
private Integer age;
private Integer hight;
private Builder() {
}
// 链式调用设置各个属性值,返回 this,即 UserBuilder(调用build()方法后,才返回Boy对象)
public Builder name(String name) {
this.name = name;
return this;
}
public Builder nickName(String nickName) {
this.nickName = nickName;
return this;
}
public Builder age(Integer age) {
this.age = age;
return this;
}
public Builder hight(Integer hight) {
this.hight = hight;
return this;
}
public Boy build() {
return new Boy(name, nickName, age, hight);
}
}
}
核心是:先把所有的属性都设置给 Builder,然后 build() 方法的时候,将这些属性复制给实际产生的对象。
看看客户端的调用:
package com.ssm.user.designPattern.builderPattern;
public class builderPatternDemo {
public static void main(String[] args) {
Boy boy = Boy.builder().name("石朔铭").nickName("ssm").age(18).hight(180).build();
System.out.println(boy);
}
}
建造者模式的链式写法很吸引人,但是,多写了很多“无用”的 builder 的代码,感觉这个模式没什么用。不过,当属性很多,而且有些必填,有些选填的时候,这个模式会使代码清晰很多。我们可以在 Builder 的构造方法中强制让调用者提供必填字段,还有,在 build() 方法中校验各个参数比在 Boy 的构造方法中校验,代码要优雅一些
题外话,强烈建议读者使用 lombok,用了 lombok 以后,上面的一大堆代码会变成如下这样:
@Builder
class Boy {
private String name;
private String nickName;
private Integer age;
private Integer hight;
}