建造者模式(Builder Pattern)
模式动机:
在某些情况下,一个对象会有一些重要的属性,在它们没有恰当的值之前,对象不能作为一个完整的产品使用。比如,一个电子邮件有发件人地址、收件人地址、主题、内容、附录等部分,而在最起码的收件人地址未被赋值之前,这个电子邮件不能发出。
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。
模式结构:
参与者:
Builder:抽象建造者
ConcreteBuilder:具体建造者
Director:指挥者
Product:产品角色
director和Builder是聚合关系(代码实现聚合的时候,成员对象通常采用构造函数注入,Setter方法参数注入。)
以快餐店为例子
汉堡可乐这些就是产品
/*
* 套餐类
*/
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 {
Meal meal = new Meal();
public abstract void buildFood();
public abstract void buildDrink();
public Meal getMeal(){
return meal;
}
}
食物类和生产食物的步骤我们都写好了,现在就可以生产各种我们要的套餐了,即具体的建造者
/*
* A套餐
*/
public class MealA extends MealBuilder{
public void buildDrink() {
meal.setDrink("一杯可乐");
}
public void buildFood() {
meal.setFood("一盒薯条");
}
}
/*
* B套餐
*/
public class MealB extends MealBuilder{
public void buildDrink() {
meal.setDrink("一杯柠檬果汁");
}
public void buildFood() {
meal.setFood("三个鸡翅");
}
}
但是客户不是直接知道生产过程的,而是通过告诉服务员直接要什么套餐然后服务员传递信息给后厨指挥生产
/*
* 服务生
*/
public class KFCWaiter {
private MealBuilder mealBuilder;
public void setMealBuilder(MealBuilder mealBuilder) {
this.mealBuilder = mealBuilder;
}
public Meal construct(){
//准备食物
mealBuilder.buildFood();
//准备饮料
mealBuilder.buildDrink();
//准备完毕,返回一个完整的套餐给客户
return mealBuilder.getMeal();
}
}
测试类
public class Client {
public static void main(String[] args) {
//服务员
KFCWaiter waiter = new KFCWaiter();
//套餐A
MealA a = new MealA();
//服务员准备套餐A
waiter.setMealBuilder(a);
//获得套餐
Meal mealA = waiter.construct();
System.out.print("套餐A的组成部分:\r\n");
System.out.println(mealA.getFood()+"\r\n"+mealA.getDrink());
}
}