建造者模式(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