这个设计模式被《Effective Java》推荐在构造器参数比较多时使用,它可以规范化创建流程和具有良好的可读性。
建造者模式:一个复杂对象的创建与它的标识分离,使得同样的构建过程可以创建不同的表示。
按照《Effective Java》写个类似的例子吧。
方便面,分为干拌面和泡面,他们都属于方便面,有面饼,不过干拌面和泡面的味道有点区别的,就需要分开写,如果直接写一般的构造器写法或者重叠构造器(其实这里还好,参数比较少),那样对客户端不太友好,不够程序化就容易出错。
建造者类一遍实现于被建造者的内部
方便面父类
class InstantNoodles{
public enum Size{Big,Mid,Small}
final Size size;
abstract static class Builder<T extends Builder<T>>{
Size size;
public T setSize(Size size){
this.size = size;
return self();
}
abstract InstantNoodles build();
protected abstract T self();
}
InstantNoodles(Builder<?> builder){
size = builder.size;
}
}
子类:
class BubbleNoodles extends InstantNoodles{
public enum Taste{Pepperbeef,Picklefish}
private final Taste taste;
public static class Builder extends InstantNoodles.Builder<Builder>{
private final Taste taste;
public Builder(Taste taste){
//保证大小不为空
this.taste = Objects.requireNonNull(taste);
}
@Override
BubbleNoodles build() {
return new BubbleNoodles(this);
}
@Override
protected Builder self() {
return this;
}
}
private BubbleNoodles(Builder builder){
super(builder);
this.taste = builder.taste;
}
@Override
public String toString() {
return "大小为"+ size +
"口味为" + taste +"泡面";
}
}
class DryNoodles extends InstantNoodles{
public enum Taste{Spicybeef}
private final Taste taste;
private boolean hamsausage = false;
public static class Builder extends InstantNoodles.Builder<Builder>{
private final Taste taste;
private boolean hamsausage = false;
public Builder(Taste taste){
//保证大小不为空
this.taste = Objects.requireNonNull(taste);
}
@Override
DryNoodles build() {
return new DryNoodles(this);
}
public Builder hamSausage(){
this.hamsausage = true;
return self();
}
@Override
protected Builder self() {
return this;
}
}
private DryNoodles(Builder builder){
super(builder);
this.taste = builder.taste;
this.hamsausage = builder.hamsausage;
}
@Override
public String toString() {
return "大小为"+ size +
"口味为" + taste +(hamsausage?"加火腿肠":"不加火腿肠")+"干拌面";
}
}
测试类:
@Test
public void test(){
BubbleNoodles instantNoodles = new BubbleNoodles.Builder(BubbleNoodles.Taste.Picklefish).setSize(InstantNoodles.Size.Big).build();
System.out.println("一桶"+instantNoodles);
DryNoodles dryNoodles = new DryNoodles.Builder(DryNoodles.Taste.Spicybeef).setSize(InstantNoodles.Size.Big).hamSausage().build();
System.out.println("一桶"+dryNoodles);
}
缺点就是,代码量真的大了好多