引言
建造者模式(Builder Pattern)使用多个简单对象一步一步构建成一个复杂的对象。这种类型的设计模式属于建造型模式,它提供了一种创建对象的最佳方式。
一个Builder会一步步构建最终的对象。该Builder类是独立于其他对象的。
实现概要
建造者模式的实现并没有一个特别经典的套路,原因是在多数情况下复杂对象的构建往往千奇百怪。但为了更好的理解建造者模式使用的场景,我们假设如下的功能需要:
因为建造者模式就是为了构建复杂对象,为了更加贴近这一点,以午餐(Meal)作为最终要被构建的对象,我们假设:午餐中分为食物(Item)和包装(Packing)—>食物包含汉堡(Burger)和冷饮(ColdDrink)两种;汉堡有鸡肉汉堡(ChickenBurger)和蔬菜汉堡(VegBurger)之分;冷饮有可口可乐(Coke)和百事可乐(Pepsi)之分;包装又分为瓶装(Bottle)和袋装(Wrapper)两种。
如果你看不懂上面的描述,或者已经准备关闭浏览器去做眼睛保健操,那么下面的结构图可能对你有所帮助:
实现过程
一、创建基础接口
创建食物接口及具体实现类,创建包装接口及具体包装类:
public interface Item {/** 食物名称*/String name();/** 包装*/Packing packing();/** 总价*/float price();
}
public abstract class Burger implements Item {@Overridepublic Packing packing() {return new Wrapper();}
}
public class ChickenBurger extends Burger {@Overridepublic String name() {return "Chicken Burger";}@Overridepublic float price() {return 50.5f;}
}
public class VegBurger extends Burger {@Overridepublic String name() {return "Veg Burger";}@Overridepublic float price() {return 25.0f;}
}
public abstract class ColdDrink implements Item {@Overridepublic Packing packing() {return new Bottle();}
}
public class Coke extends ColdDrink {@Overridepublic String name() {return "Coke";}@Overridepublic float price() {return 30.0f;}
}
public class Pepsi extends ColdDrink {@Overridepublic String name() {return "Pepsi";}@Overridepublic float price() {return 35.0f;}
}
public interface Packing {String pack();
}
public class Bottle implements Packing {@Overridepublic String pack() {return "Bottle";}
}
public class Wrapper implements Packing {@Overridepublic String pack() {return "Wrapper";}
}
二、创建目标类型
此例中,目标类型即午餐类(Meal)
public class Meal {private List<Item> items = new ArrayList<Item>();public Meal addAll(List<? extends Item> items) {this.items.addAll(items);return this;}public Double getSum() {return this.items.stream().collect(Collectors.summarizingDouble(Item::price)).getSum();}public Double getAverage() {return this.items.stream().collect(Collectors.summarizingDouble(Item::price)).getAverage();}public void showItems() {this.items.forEach(item -> {System.out.print("Item : " + item.name());System.out.print(", Packing : " + item.packing().pack());System.out.println(", Price : " + item.price());});}
}
三、创建建造者类
public class MealBuilder {public Meal prepareMeal(Item... items) {return new Meal().addAll(Arrays.asList(items));}
}
四、测试
public class BuilderPatternDemo {public static void main(String[] args) {MealBuilder mealBuilder = new MealBuilder();Meal vegMeal = mealBuilder.prepareMeal(new VegBurger(), new Coke());System.out.println("Veg Meal");vegMeal.showItems();System.out.println("Total Cost: " + vegMeal.getSum());Meal nonVegMeal = mealBuilder.prepareMeal(new ChickenBurger(), new Pepsi());System.out.println("\n\nNon-Veg Meal");nonVegMeal.showItems();System.out.println("Total Cost: " + nonVegMeal.getSum());}
}
执行结果:
总结
意图:建造者模式的用意就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示,例如本例中相同的创建午餐的方式,但使用不同的基础对象,最终得出不一样的套餐。
使用场景:一些基础部件不会变,而其组合经常变化的时候。主要解决软件系统中,有时候会面临“一个复杂对象”的创建工作,其通常由多个子对象用一定的算法构成。由于需求的变化,这个复杂对象的各个部件经常面临着剧烈的变化,但将它们组合在一起的算法相对稳定。
优点:建造者独立,易扩展;便于控制细节风险。
缺点:产品必须有共同点,范围有限制;内部变化复杂,会有很多建造类。
鸣谢
《建造者模式》