建造者模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
这个模式和模板方法模式特别相似,下面是模板方法模式的示例:
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();
}
}
可以看到饮品的构建和饮品自身的方法属性完全分离了
看到这里大家可能会感到讶异,因为我这里的建造者模式类结构和很多地方都不一样,我们看看网上最常见的定义:
下面是模板方法模式的类结构
如果算法族(模板方法模式)或者构建方式(建造者模式)是稳定的、不会发生变化的,那么建造者模式相比于模板方法模式有什么优势呢?唯一能说服我的就是将构建过程提取出来单独进行封装后,后续可以很方便的进行扩展