概念
使用多个简单的对象一步一步构建成一个复杂的对象,这个复杂对象的构建框架一般不会变,但具体组成成分却会改变。定义一个指挥者类,类中包含多个创建对象不同表现形式的方法,每个构建方法在描述构建过程的同时,也设定了构建需要的基础构件。从而将一个复杂对象的构建与它的各种表示形式分离,使得同样的构建过程可以创建不同的表示形式。(因为基础类产品可以换为同类的其他产品)
如图,这是一个Meal复杂对象的构建流程,这个流程一般不会改变,但由于具体选择的Veg Burger或Chicken Burger或pepsi或coke的不同,每次Meal对象的具体组成(表示形式)也不同。
一个复杂对象的创建工作中,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,比如替换成同一接口下的其他类(汽车轮胎A改为轮胎B),但是将它们(这些组件)组合在一起的算法却相对稳定。
优点:
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
- 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者, 用户使用不同的具体建造者即可得到不同的产品对象 。
- 可以更加精细地控制产品的创建流程 。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
缺点:
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因为没有一个相对稳定的构建框架,因此其使用范围受到一定的限制。
- 如内部变化复杂,会有很多的建造类为最终对象提供组件,导致系统变得很庞大。
建造者模式与抽象工厂模式的比较:
- 与抽象工厂模式相比, 建造者模式返回一个组装好的完整产品 ,而 抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看成 汽车配件生产工厂 ,生产一个产品族的产品,那么建造者模式就是一个 汽车组装工厂 ,通过对部件的组装可以返回一辆完整的汽车。
举例
package builder ;
public class User {
public static void main(String[] args) {
KFCWaiter pd = new KFCWaiter();
//只需要知道你要创建个什么复杂对象:new SubMealBuilderA(),然后交给指挥者
Meal mealA = pd.constructMeal(new SubMealBuilderA());
System.out.println(mealA.getFood());
System.out.println(mealA.getDrink());
Meal mealB = pd.constructMeal(new SubMealBuilderB());
System.out.println(mealB.getFood());
System.out.println(mealB.getDrink());
}
}
//套餐
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;
}
}
/*Builder:
* 给出一个抽象接口,以规范产品对象的各个组成成分的建造。
* 这个接口规定了要实现的复杂对象的各部分的创建,
* 但并不涉及具体的对象部件的创建。
* */
interface MealBuilder {
//一顿饭的基本组件
void buildFood();
void buildDrink();
//返回一个对象
Meal getMeal();
}
/*ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建,
* 当建造的产品不需要某个组件时,构建那个组件的方法不写任何操作。(看情况)
* 在建造过程完成后,提供产品的实例。
**/
//建造套餐A
class SubMealBuilderA implements MealBuilder {
Meal meal;
public SubMealBuilderA(){
meal = new Meal();
}
public void buildFood() {
meal.setFood("套餐A的Food");
}
public void buildDrink() {
meal.setDrink("套餐A的Drink");
}
public Meal getMeal() {
return meal;
}
}
//建造套餐B
class SubMealBuilderB implements MealBuilder {
Meal meal;
public SubMealBuilderB(){
meal = new Meal();
}
public void buildFood() {
meal.setFood("套餐B的Food");
}
public void buildDrink() {
meal.setDrink("套餐B的Drink");
}
public Meal getMeal() {
return meal;
}
}
/*Director:指挥具体建造者来创建某复杂对象的各个部分,
* 在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
* */
class KFCWaiter {
public Meal constructMeal(MealBuilder pb) {
pb.buildFood();
pb.buildDrink();
return pb.getMeal();
}
//也可以设定其他的具体表现形式
/*
public Meal constructMeal(){
MealBuilder subMealBuilderA = new SubMealBuilderA();
return subMealBuilderA .getMeal();
}
*/
}
Output:
套餐A的Food
套餐A的Drink
套餐B的Food
套餐B的Drink
package builder ;
public class User {
public static void main(String[] args) {
KFCWaiter pd = new KFCWaiter();
//只需要知道你要创建个什么复杂对象:new SubMealBuilderA(),然后交给指挥者
pd.setMealBuilder(new SubMealBuilderA());
Meal mealA = pd.constructMeal();
System.out.println(mealA.getFood());
System.out.println(mealA.getDrink());
pd.setMealBuilder(new SubMealBuilderB());
Meal mealB = pd.constructMeal();
System.out.println(mealB.getFood());
System.out.println(mealB.getDrink());
}
}
//套餐
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;
}
}
/*Builder:
* 给出一个抽象接口,以规范产品对象的各个组成成分的建造。
* 这个接口规定了要实现的复杂对象的各部分的创建,
* 但并不涉及具体的对象部件的创建。
* */
abstract class MealBuilder {
//一顿饭的基本组件
protected Meal meal;
protected abstract void buildFood();
protected abstract void buildDrink();
//返回一个对象
public abstract Meal getMeal();
}
/*ConcreteBuilder:实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建,
* 当建造的产品不需要某个组件时,构建那个组件的方法不写任何操作。
* 在建造过程完成后,提供产品的实例。
**/
//建造套餐A
class SubMealBuilderA extends MealBuilder {
public SubMealBuilderA(){
meal = new Meal();
}
protected void buildFood() {
meal.setFood("套餐A的Food");
}
protected void buildDrink() {
meal.setDrink("套餐A的Drink");
}
public Meal getMeal() {
return meal;
}
}
//建造套餐B
class SubMealBuilderB extends MealBuilder {
public SubMealBuilderB(){
meal = new Meal();
}
protected void buildFood() {
meal.setFood("套餐B的Food");
}
protected void buildDrink() {
meal.setDrink("套餐B的Drink");
}
public Meal getMeal() {
return meal;
}
}
/*Director:指挥具体建造者来创建某复杂对象的各个部分,
* 在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
* */
class KFCWaiter {
private MealBuilder mb;
public Meal constructMeal() {
mb.buildFood();
mb.buildDrink();
return mb.getMeal();
}
public void setMealBuilder(MealBuilder mb) {
this.mb = mb;
}
}
Output:同上