建造者模式是最复杂的建立型模式,它将客户端与包含多个组成部分的复杂对象的建立过程分离,客户端无须知道复杂对象的内部组成部分与装配部分,只需知道建造者的类型便可。java
建造者模式用于建立一个包含对个组成部分的复杂对象,能够返回一个完整的产品对象给用户。用户无须知道建立过程和内部细节,只需直接使用建立好的完整对象便可。好比汽车拥有车轮、方向盘、发送机等各类部件,用户几乎不会单独使用某个部件,而是使用一辆完整的汽车。软件开发中也存在相似汽车同样的复杂对象,它们拥有一系列成员属性,并且可能存在一些限制条件。ide
将一个复杂对象的构建与它的表示分离,使得一样的构建过程能够建立不一样的表示。建造者模式是一步一步建立一个复杂对象,容许用户经过指定复杂对象的类型和内容构建它们,用户不须要知道内部具体构建细节。函数
Builder(抽象建造者)工具
为建立Product对象的各个部件指定抽象接口,方法buildPartX()用于建立复杂对象的各个部件;另外一个方法getResult()用于返回复杂对象。测试
ConcreteBuilder(具体建造者)ui
具体建造者实现Builder接口,实现各部件的构造和装配方法,定义并明确它所建立的复杂对象,也能够提供一个方法返回建立好的复杂产品对象。this
Product(产品角色)code
产品角色是被构建的复杂对象,包含多个组成部件,具体建造者建立该产品的内部表示并定义它的装配过程。xml
Director(指挥者)对象
负责安排复杂对象的建造次序,指挥者与抽象建造者之间存在关联关系,能够在其construct()建造方法中调用建造者对象的部件构造与装配方法,完成复杂对象的建造。客户端只需与指挥者进行交互,在客户端肯定建造者的类型,并实例化具体建造者对象(也可经过配置文件和反射机制),而后经过指挥者类的构造函数或者set方法将该对象传入指挥者类中。
套餐是一个复杂对象,通常包含主食(如汉堡、鸡肉卷等)和饮料(若是汁、可乐)等组成部分。不一样套餐有不一样的组成部分,KFC服务员根据顾客需求,一步一步装填这些组成部分,构造一份完整的套餐,而后返回给顾客。
产品类Meal
套餐Meal是复杂产品对象,它包括两个成员属性food和drink,其中food表示主食,drink表示饮料,Meal中还包括成员属性的Getter方法和Setter方法。
public class Meal { //部件 private String food; private String drink; public String getDrink() { return drink; } public void setDrink(String drink) { this.drink = drink; } public String getFood() { return food; } public void setFood(String food) { this.food = food; } }
抽象建造者类MealBuilder(套餐建造者类)
MealBuilder是套餐建造者,它是一个抽象类,声明了抽象的部件组装方法buildFood()和buildDrink(),在MealBuilder中定义Meal类型的对象meal,提供工厂方法getMeal()用于返回meal对象。
public abstract class MealBuilder { protected Meal meal = new Meal(); public abstract void buildFood(); public abstract void buildDrink(); public Meal getMeal() { return meal; } }
具体建造者类SubMealBuilderA(A套餐建造者类)
SubMealBuilderA是具体建造者类,用于建立A套餐,它是抽象建造者类的子类,实现了抽象建造者类中声明的部件的组装方法。
public class SubMealBuilderA extends MealBuilder { @Override public void buildFood() { meal.setFood("一个鸡腿堡"); } @Override public void buildDrink() { meal.setDrink("一杯可乐"); } }
具体建造者类SubMealBuilderB(B套餐建造者类)
public class SubMealBuilderB extends MealBuilder { @Override public void buildFood() { meal.setFood("一个鸡肉卷"); } @Override public void buildDrink() { meal.setDrink("一杯果汁"); } }
指挥者类KFCWaiter(服务员类)
KFCWaiter类是指挥者类,在KFC套餐制做过程当中至关于KFC服务员,客户端指定具体建造者类型,在其construct()方法中调用指定建造者对象的部件组装方法和工厂方法。
public class KFCWaiter { private MealBuilder mealBuilder; public void setMealBuilder(MealBuilder mealBuilder) { this.mealBuilder = mealBuilder; } public Meal construct() { mealBuilder.buildFood(); mealBuilder.buildDrink(); return mealBuilder.getMeal(); } }
XML操做工具类
public class XMLUtil { public static Object getBean() throws Exception { //建立解析器工厂 DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance(); //建立解析器 DocumentBuilder builder = builderFactory.newDocumentBuilder(); //获得document Document document = builder.parse("config.xml"); //获取包含品牌名称的文本节点 NodeList brandNameList = document.getElementsByTagName("className"); Node classNode = brandNameList.item(0).getFirstChild(); String className = classNode.getNodeValue().trim(); Class c = Class.forName("com.builderPattern." + className); Object o = c.newInstance(); return o; } }
配置文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <className>SubMealBuilderA</className> </configuration>
测试类
public class Test { public static void main(String[] args) throws Exception { //动态肯定套餐种类 MealBuilder mealBuilder = (MealBuilder) XMLUtil.getBean(); //服务员是指挥者 KFCWaiter waiter = new KFCWaiter(); //服务员准备套餐 waiter.setMealBuilder(mealBuilder); //客户得到套餐 Meal meal = waiter.construct(); System.out.println("套餐组成:"); System.out.println(meal.getDrink()); System.out.println(meal.getFood()); } }
结果分析
若是在配置文件将节点中内容设置为 SubMealBuilderA,则输出结果以下:
若是在配置文件将节点中内容设置为 SubMealBuilderB,则输出结果以下:
更换具体建造者无须修改源代码,只修改配置文件便可。若是须要增长新的具体建造者,只需增长一个新的具体建造者类继承抽象建造者类,再实现其中声明的抽象部件组装方法,修改配置文件,便可使用新的具体建造者构造新的类型的套餐,系统具备良好的灵活性和可扩展性,符合开闭原则的要求。