建造者模式(builder pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 builder 类会一步一步构造最终的对象。该 builder 类是独立于其他对象的。
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、java 中的 stringbuilder。
优点: 1、建造者独立,易扩展。 2、便于控制细节风险。
缺点: 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。
使用场景: 1、需要生成的对象具有复杂的内部结构。 2、需要生成的对象内部属性本身相互依赖。
注意事项:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(burger)和一杯冷饮(cold drink)。汉堡(burger)可以是素食汉堡(veg burger)或鸡肉汉堡(chicken burger),它们是包在纸盒中。冷饮(cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。
我们将创建一个表示食物条目(比如汉堡和冷饮)的 item 接口和实现 item 接口的实体类,以及一个表示食物包装的 packing 接口和实现 packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。
然后我们创建一个 meal 类,带有 item 的 arraylist 和一个通过结合 item 来创建不同类型的 meal 对象的 mealbuilder。builderpatterndemo,我们的演示类使用 mealbuilder 来创建一个 meal。
创建一个表示食物条目和食物包装的接口。
item.java
public interface item {
public string name();
public packing packing();
public float price();
}
packing.java
public interface packing {
public string pack();
}
创建实现 packing 接口的实体类。
wrapper.java
public class wrapper implements packing {
@override
public string pack() {
return "wrapper";
}
}
bottle.java
public class bottle implements packing {
@override
public string pack() {
return "bottle";
}
}
创建实现 item 接口的抽象类,该类提供了默认的功能。
burger.java
public abstract class burger implements item {
@override
public packing packing() {
return new wrapper();
}
@override
public abstract float price();
}
colddrink.java
public abstract class colddrink implements item {
@override
public packing packing() {
return new bottle();
}
@override
public abstract float price();
}
创建扩展了 burger 和 colddrink 的实体类。
vegburger.java
public class vegburger extends burger {
@override
public float price() {
return 25.0f;
}
@override
public string name() {
return "veg burger";
}
}
chickenburger.java
public class chickenburger extends burger {
@override
public float price() {
return 50.5f;
}
@override
public string name() {
return "chicken burger";
}
}
coke.java
public class coke extends colddrink {
@override
public float price() {
return 30.0f;
}
@override
public string name() {
return "coke";
}
}
pepsi.java
public class pepsi extends colddrink {
@override
public float price() {
return 35.0f;
}
@override
public string name() {
return "pepsi";
}
}
创建一个 meal 类,带有上面定义的 item 对象。
meal.java
import java.util.arraylist;
import java.util.list;
public class meal {
private list<item> items = new arraylist<item>();
public void additem(item item){
items.add(item);
}
public float getcost(){
float cost = 0.0f;
for (item item : items) {
cost += item.price();
}
return cost;
}
public void showitems(){
for (item item : items) {
system.out.print("item : "+item.name());
system.out.print(", packing : "+item.packing().pack());
system.out.println(", price : "+item.price());
}
}
}
创建一个 mealbuilder 类,实际的 builder 类负责创建 meal 对象。
mealbuilder.java
public class mealbuilder {
public meal preparevegmeal (){
meal meal = new meal();
meal.additem(new vegburger());
meal.additem(new coke());
return meal;
}
public meal preparenonvegmeal (){
meal meal = new meal();
meal.additem(new chickenburger());
meal.additem(new pepsi());
return meal;
}
}
buiderpatterndemo 使用 mealbuider 来演示建造者模式(builder pattern)。
builderpatterndemo.java
public class builderpatterndemo {
public static void main(string[] args) {
mealbuilder mealbuilder = new mealbuilder();
meal vegmeal = mealbuilder.preparevegmeal();
system.out.println("veg meal");
vegmeal.showitems();
system.out.println("total cost: " +vegmeal.getcost());
meal nonvegmeal = mealbuilder.preparenonvegmeal();
system.out.println("\n\nnon-veg meal");
nonvegmeal.showitems();
system.out.println("total cost: " +nonvegmeal.getcost());
}
}
验证输出。
veg meal item : veg burger, packing : wrapper, price : 25.0 item : coke, packing : bottle, price : 30.0 total cost: 55.0 non-veg meal item : chicken burger, packing : wrapper, price : 50.5 item : pepsi, packing : bottle, price : 35.0 total cost: 85.5