一.模式定义
对象创建型模式。实现复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。
建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。
Builder Pattern: Separate the construction of a complex object from its representation so that the same construction process can create different representations.
二.模式要素
建造者:负责以组装的形式生产出所需要的产品
零件:构成产品所需要的必要零件
产品:具体的产品,由零件灵活拼装而成
调用者
三.举例说明
在日常生活中我们一定有过去小饭店吃饭的经历,一些特色小店提供美味的主食和饮料,能够让人大快朵颐。
假设你开了一家小饭店,提供主食和饮料。其中主食有现烤面包、牛肉面,饮料有鲜榨橙汁、柠檬水。每来一位顾客都必须点单,不管其点了什么,点了多少,都能够组成一顿饭,关系图如下。现在作为饭店老板的你在想,当顾客点完一餐后,我需要根据顾客的点餐情况安排厨师去做,并且要知道这一餐的明细和总价,那怎么办呢?
很简单,建造者模式走起!
四.具体实例
工程结构如下:
1.IFood.java 主食接口
package builder;
/**
* @program: DesignModes
* @description: 主食接口
* @author: Lei Dong
* @create: 2018-10-04 10:38
**/
public interface IFood {
/**
* 名称
*/
String showName();
/**
* 价格
*/
int showPrice();
}
2.Bread.java 现烤面包
package builder;
/**
* @program: DesignModes
* @description: 面包
* @author: Lei Dong
* @create: 2018-10-04 10:44
**/
public class Bread implements IFood {
private String name = "现烤面包";
private int price = 6;
@Override
public String showName() {
return this.name;
}
@Override
public int showPrice() {
return this.price;
}
}
3.Noodles.java 牛肉面
package builder;
/**
* @program: DesignModes
* @description: 面条
* @author: Lei Dong
* @create: 2018-10-04 10:58
**/
public class Noodles implements IFood {
private String name = "牛肉面";
private int price = 15;
@Override
public String showName() {
return this.name;
}
@Override
public int showPrice() {
return this.price;
}
}
4.IDrink.java 饮料接口
package builder;
/**
* @program: DesignModes
* @description: 饮料接口
* @author: Lei Dong
* @create: 2018-10-04 10:36
**/
public interface IDrink {
/**
* 名称
*/
String showName();
/**
* 价格
*/
int showPrice();
}
5.OrangeJuice.java 鲜榨橙汁
package builder;
/**
* @program: DesignModes
* @description: 橙汁饮料
* @author: Lei Dong
* @create: 2018-10-04 10:39
**/
public class OrangeJuice implements IDrink {
private String name = "鲜榨橙汁";
private int price = 10;
@Override
public String showName() {
return this.name;
}
@Override
public int showPrice() {
return this.price;
}
}
6.Lemonade.java 柠檬水
package builder;
/**
* @program: DesignModes
* @description: 柠檬水饮料
* @author: Lei Dong
* @create: 2018-10-04 10:42
**/
public class Lemonade implements IDrink {
private String name = "柠檬水";
private int price = 2;
@Override
public String showName() {
return this.name;
}
@Override
public int showPrice() {
return this.price;
}
}
7.Meal.java 餐
package builder;
import java.util.List;
/**
* @program: DesignModes
* @description: 套餐
* @author: Lei Dong
* @create: 2018-10-04 10:47
**/
class Meal {
List<IFood> foodList;
List<IDrink> drinkList;
/**
* 展示详情
*/
void showDetail() {
System.out.println("主食:");
for(int i = 0; i < foodList.size(); i++) {
System.out.println(foodList.get(i).showName());
}
System.out.println();
System.out.println("饮料:");
for(int i = 0; i < drinkList.size(); i++) {
System.out.println(drinkList.get(i).showName());
}
}
/**
* 展示总价
*/
void showTotalPrice() {
int totalPrice = 0;
for(int i = 0; i < foodList.size(); i++) {
totalPrice += foodList.get(i).showPrice();
}
for(int i = 0; i < drinkList.size(); i++) {
totalPrice += drinkList.get(i).showPrice();
}
System.out.println("总价:" + totalPrice + "元");
}
}
8.MealBuilder.java 餐建造者
package builder;
import java.util.ArrayList;
/**
* @program: DesignModes
* @description: 套餐建造者
* @author: Lei Dong
* @create: 2018-10-04 10:47
**/
class MealBuilder {
private Meal meal;
Meal obtainMeal() {
return this.meal;
}
MealBuilder() {
meal = new Meal();
meal.drinkList = new ArrayList<>();
meal.foodList = new ArrayList<>();
}
/**
* 添加主食
*
* @param food
*/
void addFood(IFood food) {
if (food != null) {
meal.foodList.add(food);
}
}
/**
* 添加饮料
*
* @param drink
*/
void addDrink(IDrink drink) {
if (drink != null) {
meal.drinkList.add(drink);
}
}
}
9.Main.java 调用者
package builder;
/**
* @program: DesignModes
* @description: Main
* @author: Lei Dong
* @create: 2018-10-04 10:35
**/
public class Main {
public static void main(String[] args) {
MealBuilder builder = new MealBuilder();
builder.addDrink(new OrangeJuice());
builder.addFood(new Noodles());
builder.addFood(new Noodles());
Meal meal = builder.obtainMeal();
meal.showDetail();
System.out.println();
meal.showTotalPrice();
}
}
运行结果;
五.总结
1.建造者模式优点
(1)客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
(2)每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
(3)可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
(4)增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
2.建造者模式缺点
(1)建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
(2)如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。