1.建造者模式
无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发动机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。根据中文翻译的不同,建造者模式又可以称为生成器模式。
建造者模式包含如下角色: - Builder:抽象建造者 - ConcreteBuilder:具体建造者 - Director:指挥者 - Product:产品角色
2.实例
建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。
项目结构图如下:


定义抽象产品
public class Meal {
//主食
private String food;
//饮料
private String drink;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getDrink() {
return drink;
}
public void setDrink(String drink) {
this.drink = drink;
}
}
定义抽象建造者
public abstract class MealBuilder {
protected Meal meal=new Meal();
public abstract void buildFood();
public abstract void buildDrink();
public Meal getMeal(){
return meal;
}
}
定义两个套餐的具体建造者
//SubMealBuilderA.java
public class SubMealBuilderA extends MealBuilder {
@Override
public void buildFood() {
meal.setFood("一个鸡腿汉堡");
}
@Override
public void buildDrink() {
meal.setDrink("一杯可乐");
}
}
//SubMealBuilderB.java
public class SubMealBuilderB extends MealBuilder {
@Override
public void buildFood() {
meal.setFood("一个鸡肉卷");
}
@Override
public void buildDrink() {
meal.setDrink("一杯果汁");
}
}
创建指挥者(Waiter)
public class KFCWaiter {
private MealBuilder mealBuilder;
public void setMealBuilder(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal construct(){
this.mealBuilder.buildFood();
this.mealBuilder.buildDrink();
return this.mealBuilder.getMeal();
}
}
XML解析工具类
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class XmlUtils {
public static Object getBean(){
DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
try {
DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
Document doc=documentBuilder.parse(XmlUtils.class .getClassLoader().getResourceAsStream("config.xml"));
String className=doc.getElementsByTagName("className").item(0).getTextContent();
return Class.forName(className).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
配置文档
<?xml version="1.0"?>
<config>
<!-- <className>com.simoniu.domain.SubMealBuilderA</className> -->
<className>com.simoniu.domain.SubMealBuilderB</className>
</config>
测试类
public class TestBuilder01 {
public static void main(String[] args) {
//动态确定套餐种类
MealBuilder mealBuilder=(MealBuilder) XmlUtils.getBean();
//服务员是指挥者
KFCWaiter kfcWaiter=new KFCWaiter();
//服务员准备套餐
kfcWaiter.setMealBuilder(mealBuilder);
//客户获取套餐
Meal meal=kfcWaiter.construct();
System.out.println("套餐组成:");
System.out.println(meal.getFood());
System.out.println(meal.getDrink());
}
}
运行结果:
套餐组成:
一个鸡肉卷
一杯果汁