简介
对于创建复杂对象时,建造者模式(Builder Pattern)提供了一种清晰、灵活的方法,尤其适用于当对象包含多个属性时,能够避免构造器混乱,增强代码的可读性和可维护性。当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。
场景举例:
要搞懂建造者的好处,我更倾向于先从"反面"教材入手:
当一个类的构造函数参数超过4个,而且这些参数有些是可选的时,我们通常有两种办法来构建它的对象。 例如我们现在有如下一个类,汉堡类Hamburger,其中meat与bread是必填参数,而其他3个是可选参数,那么我们如何构造这个类的实例呢,通常有两种常用的方式:
public class Hamburger {
private final String meat; // 必选
private final String bread; // 必选
private final String vegetable; // 可选
private final String pickle; // 可选
private final String sauce; // 可选
}
第一:折叠构造函数模式,也是我们经常用的一种
弊端:当我们new Hamburger的时候,里面一堆参数。
public class Hamburger {
......
public Hamburger(String meat, String bread) {
this.meat = meat;
this.bread = bread;
}
public Hamburger(String meat, String bread, String vegetable) {
this.meat = meat;
this.bread = bread;
this.vegetable = vegetable;
}
public Hamburger(String meat, String bread, String vegetable, String pickle) {
this.meat = meat;
this.bread = bread;
this.vegetable = vegetable;
this.pickle = pickle;
}
public Hamburger(String meat, String bread, String vegetable, String pickle, String sauce) {
this.meat = meat;
this.bread = bread;
this.vegetable = vegetable;
this.pickle = pickle;
this.sauce = sauce;
}
}
第二种:JavaBean
弊端:类中的属性是分步设置的,容易出错。
public class Hamburger {
......
public String getMeat() {
return meat;
}
public void setMeat(String meat) {
this.meat = meat;
}
public String getBread() {
return bread;
}
public void setBread(String bread) {
this.bread = bread;
}
......
}
而 Builder 模式就解决了这两个弊端
UML类图:
代码实现
如何实现?
- 在Hamburger 中创建一个静态内部类 Builder,然后将Hamburger 中的参数都复制到Builder类中。
- 在Hamburger中创建一个private的构造函数,参数为Builder类型
- 在Builder中创建一个
public
的构造函数,参数为Hamburger中必填的那些参数,meat和bread。 - 在Builder中创建设置函数,对Hamburger中那些可选参数进行赋值,返回值为Builder类型的实例
- 在Builder中创建一个
build()
方法,在其中构建Hamburger的实例并返回
代码如下:
public class Hamburger {
private final String meat; // 牛肉
private final String bread; // 面包
private final String vegetable; // 蔬菜
private final String pickle; // 酸黄瓜
private final String sauce; // 沙拉酱
private Hamburger(Builder builder) {
this.meat = builder.meat;
this.bread = builder.bread;
this.vegetable = builder.vegetable;
this.pickle = builder.pickle;
this.sauce = builder.sauce;
}
public static class Builder {
private String meat; // 必须
private String bread; // 必须
private String vegetable; // 可选
private String pickle; // 可选
private String sauce; // 可选
public Builder(String meat, String bread) {
this.meat = meat;
this.bread = bread;
}
public Builder setVegetable(String vegetable){
this.vegetable = vegetable;
return this;
}
public Builder setPickle(String pickle){
this.pickle = pickle;
return this;
}
public Builder setSauce(String sauce){
this.sauce = sauce;
return this;
}
public Hamburger build(){
return new Hamburger(this);
}
}
@Override
public String toString() {
return "Hamburger{" +
"meat='" + meat + '\'' +
", bread='" + bread + '\'' +
", vegetable='" + vegetable + '\'' +
", pickle='" + pickle + '\'' +
", sauce='" + sauce + '\'' +
'}';
}
}
客户端调用:(优雅起来了)
Hamburger hamburger = new Hamburger.Builder("牛肉", "面包")
.setVegetable("加蔬菜")
.setPickle("加酸黄瓜")
.setSauce("加沙拉")
.build();
打印后:
Hamburger{meat='牛肉', bread='面包', vegetable='加蔬菜', pickle='加酸黄瓜', sauce='加沙拉'}
总结
最后,如果你从本文中有所收获,可否点赞转发支持一下博主,你小小的鼓励,是激发博主持续写作的动力...