Builder 模式
引入
这个设计模式有什么用,解决什么问题,为什么要用
- 一个类有很多的field,构造函数很复杂
- 处理对象的不可变性
例子
- StringBuilder
- DocumentBuiler
- Locale.Builder
详解
例1
现有一个“订餐类”LunchOrderBean,其中有属性面包,调料,肉等等属性
实现一:默认构造函数和setter方法
public class LunchOrderBean {
private String bread;
private String condiments;
private String dressing;
private String meat;
public LunchOrderBean() {
}
public String getBread() {
return bread;
}
public String getCondiments() {
return condiments;
}
public String getDressing() {
return dressing;
}
public String getMeat() {
return meat;
}
public void setBread(String bread) {
this.bread = bread;
}
public void setCondiments(String condiments) {
this.condiments = condiments;
}
public void setDressing(String dressing) {
this.dressing = dressing;
}
public void setMeat(String meat) {
this.meat = meat;
}
}
我们要使用这个类,也就是获取这个类的对象,如何做?
很简单,就像下面这样
LunchOrderBean lunchOrderBean = new LunchOrderBean();
lunchOrderBean.setBread("Wheat");
lunchOrderBean.setCondiments("Lettuce");
lunchOrderBean.setDressing("Mustard");
lunchOrderBean.setMeat("Ham");
System.out.println(lunchOrderBean.getBread());
System.out.println(lunchOrderBean.getCondiments());
System.out.println(lunchOrderBean.getDressing());
System.out.println(lunchOrderBean.getMeat());
我们看到这个类有一个默认的无参数的构造函数,且对每个属性都有setter方法。
但是这样的问题是:
- 类LunchOrderBean不是不可变的(immutable),这意味着在创建它的对象后,我们可以通过setter方法来改变对象的状态
- 从类本身看不出类的使用规范或说明,也就是说我们看不出对一个合法的order来说,哪些属性是必须的,哪些是可选的。
实现二 层叠(telescoping)构造函数
public class LunchOrderTele {
private String bread;
private String condiments;
private String dressing;
private String meat;
public LunchOrderTele(String bread) {
this.bread = bread;
}
public LunchOrderTele(String bread, String condiments) {
this(bread);
this.condiments = condiments;
}
public LunchOrderTele(String bread, String condiments, String dressing) {
this(bread, condiments);
this.dressing = dressing;
}
public LunchOrderTele(String bread, String condiments, String dressing, String meat) {
this(bread, condiments, dressing);
this.meat = meat;
}
public String getBread() {
return bread;
}
public String getCondiments() {
return condiments;
}
public String getDressing() {
return dressing;
}
public String getMeat() {
return meat;
}
}
这个实现消除了setter方法,解决了“不可变”的问题。
并且使用了很多构造函数,我们称为层叠(telescoping)构造函数,让我们可以创建我们想要的order,只有面包的,有面包和调料的,有面包和调料和肉的等等。
但是它没有列举出所有情况,假如我们想要一个只有面包和肉的,它就无能为力了。
实现三 builder模式
public class LunchOrder {
public static class Builder {
private String bread;
private String condiments;
private String dressing;
private String meat;
public Builder() {
}
public LunchOrder build() {
return new LunchOrder(this);
}
public Builder bread(String bread) {
this.bread = bread;
return this;
}
public Builder condiments(String condiments) {
this.condiments = condiments;
return this;
}
public Builder dressing(String dressing) {
this.dressing = dressing;
return this;
}
public Builder meat(String meat) {
this.meat = meat;
return this;
}
}
private final String bread;
private final String condiments;
private final String dressing;
private final String meat;
private LunchOrder(Builder builder) {
this.bread = builder.bread;
this.condiments = builder.condiments;
this.dressing = builder.dressing;
this.meat = builder.meat;
}
public String getBread() {
return bread;
}
public String getCondiments() {
return condiments;
}
public String getDressing() {
return dressing;
}
public String getMeat() {
return meat;
}
}
网友评论