建造者模式(Builder Pattern)

建造者模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

这个模式和模板方法模式特别相似,下面是模板方法模式的示例:


public abstract class Beverage {

    public abstract void addIngredient();

    public void addHotWater(){
        System.out.println("加热水");
    }

    public void brew(){
        System.out.println("冲泡");
    }

    public abstract void addCondiment();

    public void prepareBeverage(){
        addIngredient();
        addHotWater();
        brew();
        addCondiment();
    }
}
public class Coffee extends Beverage {

    public void addIngredient(){
        System.out.println("加咖啡粉");
    }

    public void addCondiment(){
        System.out.println("加糖");
    }
}
public class LemonTea extends Beverage {

    public void addIngredient(){
        System.out.println("加茶叶");
    }

    public void addCondiment(){
        System.out.println("加柠檬汁");
    }
}

调用方代码如下:

public class Test {
    public static void main(String[] args) {
        Beverage b = new Coffee();
        b.prepareBeverage();
    }
}

由于被Beverage类中的prepareBeverage方法所限制,先放咖啡和糖,再加热水这种动作是不可能发生的,同样先放热水,后放茶叶的做法也是行不通的,真实的场景下,即便是“模板”,也会经常发生变化,而面对变化,模板方法模式的适应性显然不是很好,我们必须对Beverage类进行改造

public abstract class Beverage {

    public abstract void addIngredient();

    public void addHotWater(){
        System.out.println("加热水");
    }

    public void brew(){
        System.out.println("冲泡");
    }

    public abstract void addCondiment();

    // 主料 - 热水 - 搅拌 - 配料
    public void prepareBeverage1(){
        addIngredient();
        addHotWater();
        brew();
        addCondiment();
    }

    // 主料 - 热水 - 搅拌 - 配料
    public void prepareBeverage2(){
        addHotWater();
        addIngredient();
        brew();
        addCondiment();
    }

    // 主料 - 配料 - 热水 - 搅拌
    public void prepareBeverage3(){
        addIngredient();
        addCondiment();
        addHotWater();
        brew();
    }
}

修改后暂时能够满足当前的需求了,但是如果流程再次发生变动,还是需要对Beverage类进行修改,明显违背了OO设计原则中的开闭原则(对扩展开放,对修改关闭),看下面的设计

首先将饮品的构建过程从Beverage类中抽离


BeverageBuilder类中有重复性代码,将重复性的代码进行抽象


public abstract class Beverage {

    public abstract void addIngredient();

    public void addHotWater(){
        System.out.println("加热水");
    }

    public void brew(){
        System.out.println("冲泡");
    }

    public abstract void addCondiment();
}
public abstract class BeverageBuilder {
    protected Beverage beverage;

    public BeverageBuilder(Beverage beverage){
        beverage = beverage;
    }

    public abstract void build();
}
public class CoffeeBuilder extends BeverageBuilder{

    public CoffeeBuilder(Beverage beverage){
        super(beverage);
    }

    // 主料 - 配料 - 热水 - 搅拌
    public void build(){
        beverage.addIngredient();
        beverage.addCondiment();
        beverage.addHotWater();
        beverage.brew();
    }
}
public class TeaBuilder extends BeverageBuilder {

    public TeaBuilder(Beverage beverage){
        super(beverage);
    }

    // 主料 - 热水 - 搅拌
    public void build(){
        beverage.addIngredient();
        beverage.addHotWater();
        beverage.brew();
    }
}

可以看到饮品的构建和饮品自身的方法属性完全分离了

看到这里大家可能会感到讶异,因为我这里的建造者模式类结构和很多地方都不一样,我们看看网上最常见的定义:


下面是模板方法模式的类结构


如果算法族(模板方法模式)或者构建方式(建造者模式)是稳定的、不会发生变化的,那么建造者模式相比于模板方法模式有什么优势呢?唯一能说服我的就是将构建过程提取出来单独进行封装后,后续可以很方便的进行扩展


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值