设计模式[4]-建造者模式
建造者模式
建造者模式是将一个复杂对象,解构为多个简单的对象,然后一步一步慢慢构造成原对象。
建造者模式主要包括四种角色:
- 抽象建造者:具有产品的多个子部件的抽象接口,最终可以返回完整产品
- 具体建造者:对抽象建造者的实现,有多个子部件的具体生成方法
- 产品角色:一个复杂对象,由建造者来构造它的不同子部件。
- 指挥者:调用建造者对产品子部件的构建,可以决定创建子部件的顺序
例子
如果我们要创建一个产品角色:一瓶瓶装饮料,它是由瓶身,液体,商标组成,现在我们要创建一瓶可乐饮料和一瓶雪碧饮料,那么我们就可以用建造者模式来实现这个需求。
- 抽象建造者:Builder,拥有构造产品角色部件的三个方法和返回完整Beverage 对象的方法。
- 具体建造者:ColaBuilder和SpriteBuilder,各自实现Builder的方法。
- 产品角色:Beverage 饮料类,包含bottler,liquid,label对象。
- 指挥者:Director,装载不同Builder,按一定顺序创建bottler,liquid,label对象,最终返回完整Beverage对象。
产品角色:饮料类:Beverage
@Data
public class Beverage {
private String bottle;
private String liquid;
private String label;
@Override
public String toString() {
return "Beverage{" +
"bottle='" + bottle + '\'' +
", liquid='" + liquid + '\'' +
", label='" + label + '\'' +
'}';
}
}
抽象建造者:Builder:
public abstract class Builder {
protected Beverage beverage = new Beverage();
/**
* 构建瓶子对象
*/
abstract void builderBottle();
/**
* 构建液体对象
*/
abstract void builderLiquid();
/**
* 构建商标对象
*/
abstract void builderLabel();
/**
* 构建饮料对象
*/
abstract Beverage build();
}
具体建造者:
每种具体产品都实现具体的建造者。
可乐建造者:ColaBuilder:
public class ColaBuilder extends Builder {
@Override
public void builderBottle() {
beverage.setBottle("透明瓶子");
}
@Override
public void builderLiquid() {
beverage.setLiquid("黑色汽水");
}
@Override
public void builderLabel() {
beverage.setLabel("Cola~");
}
@Override
public Beverage build() {
return beverage;
}
}
雪碧建造者:SpriteBuilder:
public class SpriteBuilder extends Builder{
@Override
public void builderBottle() {
beverage.setBottle("绿色瓶子");
}
@Override
public void builderLiquid() {
beverage.setLiquid("白色汽水");
}
@Override
public void builderLabel() {
beverage.setLabel("Sprite~");
}
@Override
public Beverage build() {
return beverage;
}
}
指挥者:Director:
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
/**
* 指挥者决定构造的顺序,最后返回完整的对象
*/
public Beverage construct() {
this.builder.builderBottle();
this.builder.builderLiquid();
this.builder.builderLabel();
return this.builder.build();
}
}
测试:
class DirectorTest {
@Test
void construct() {
Director director = new Director(new ColaBuilder());
Beverage beverage = director.construct();
System.out.println(beverage);
director = new Director(new SpriteBuilder());
beverage = director.construct();
System.out.println(beverage);
}
}
输出:
Beverage{bottle='透明瓶子', liquid='黑色汽水', label='Cola~'}
Beverage{bottle='绿色瓶子', liquid='白色汽水', label='Sprite~'}
分析
建造者模式可以对子部件的模块的创建进行控制,最终再获得完整的产品。这和工厂模式的侧重点不同,工厂模式注重完整对象的创建过程,建造者模式注重零件的组装过程。而且建造者可以在指挥者角色中控制子部件的组装顺序,顺序不同,最终组装的产品也有可以不同,这也是它的特点。
拓展
用建造者模式实现链式赋值:
以上面的例子Beverage为例,如果我们想直接新建一个Beverage实例并给他赋值,我们的代码应该是:
void test() {
Beverage beverage = new Beverage();
beverage.setLabel("标签");
beverage.setLiquid("液体");
beverage.setBottle("瓶子");
System.out.println(beverage);
}
接下来,我们利用建造者模式实现链式赋值。
我重新建了一个BeverageChain类来展示这个效果。
首先先去掉三个属性的get和set方法,然后创建私有的构造方法,接收的参数就是建造者对象,最后创建一个内部类当作建造者,用来建造三个参数,为了使用方便,变量名和方法名都是用同样的单词,最后在build方法,创建一个BeverageChain类返回完成建造。
public class BeverageChain {
private String bottle;
private String liquid;
private String label;
private BeverageChain(Builder builder) {
this.bottle = builder.bottle;
this.liquid = builder.liquid;
this.label = builder.label;
}
@Override
public String toString() {
return "BeverageChain{" +
"bottle='" + bottle + '\'' +
", liquid='" + liquid + '\'' +
", label='" + label + '\'' +
'}';
}
public static class Builder {
private String bottle;
private String liquid;
private String label;
public Builder() {
}
public Builder bottle(String bottle) {
this.bottle = bottle;
return this;
}
public Builder liquid(String liquid) {
this.liquid = liquid;
return this;
}
public Builder label(String label) {
this.label = label;
return this;
}
public BeverageChain build() {
return new BeverageChain(this);
}
}
}
测试:
@Test
void chained() {
BeverageChain.Builder builder = new BeverageChain.Builder();
BeverageChain beverage = builder.bottle("瓶子").label("标签").liquid("液体").build();
System.out.println(beverage);
}
输出:
BeverageChain{bottle='瓶子', liquid='液体', label='标签'}