1. 概述
建造者模式也称为:生成器模式
定义:建造者模式是一种创建型设计模式,它允许你将创建复杂对象的步骤与表示方式相分离。
解释:建造者模式就是将复杂对象的创建过程拆分成多个简单对象的创建过程,并将这些简单对象组合成复杂对象!
2. 优缺点
优点 | 缺点 |
|
|
|
|
|
3. 结构
建造者模式包含以下几个主要角色:
- 产品(Product):要构建的复杂对象;产品类通常包含多个部分或者属性,并由具体的建造者逐步构建而成。
- 抽象建造者(Builder):定义了构建产品的抽象接口,包括构建产品的各个部分的方法;通常包括多个构建方法和一个返回产品的方法。
- 具体建造者(Concrete Builder):实现了抽象建造者接口,具体确定如何构建产品的各个部分,并负责返回最终构建的产品。
- 指导者(Director):负责调用建造者的方法来构建产品;指导者并不了解具体的构建过程,只关心产品的构建顺序和方式。
4. 代码实现
4.1. 需求介绍
我们假设一个快餐店的商业案例,其中,一个典型的套餐可以是一个汉堡(Burger)和一杯冷饮(Cold drink)。汉堡(Burger)可以是素食汉堡(Veg Burger)或鸡肉汉堡(Chicken Burger),它们是包在纸盒中。冷饮(Cold drink)可以是可口可乐(coke)或百事可乐(pepsi),它们是装在瓶子中。
我们将创建一个表示食物条目(比如汉堡和冷饮)的 Item 接口和实现 Item 接口的实体类,以及一个表示食物包装的 Packing 接口和实现 Packing 接口的实体类,汉堡是包在纸盒中,冷饮是装在瓶子中。
然后我们创建一个 Meal 类,带有 Item 的 ArrayList 和一个通过结合 Item 来创建不同类型的 Meal 对象的 MealBuilder。BuilderPatternDemo 类使用 MealBuilder 来创建一个 Meal。
4.2. 代码演示
- 创建一个代表食物条目和食物包装的接口。
/**
* @Description 食品条目接口
* @Author gongming.Zhang
* @Date 2024/11/1 15:54
* @Version 1.0
*/
public interface Item {
// 商品名称
String name();
// 包装类型 (纸盒、瓶子)
Packing packing();
// 价格
float price();
}
package top.zhang.builderdesignpatterns.entity.packing;
/**
* @Description 食物包装条目接口
* @Author gongming.Zhang
* @Date 2024/11/1 15:56
* @Version 1.0
*/
public interface Packing {
// 包装类型(纸盒、瓶子)
String pack();
}
- 创建并实现
Packing
接口的实体类。
/**
* @Description 纸盒实现类
* @Author gongming.Zhang
* @Date 2024/11/1 15:57
* @Version 1.0
*/
public class Wrapper implements Packing {
@Override
public String pack() {
return "Wrapper";
}
}
/**
* @Description 瓶子实现类
* @Author gongming.Zhang
* @Date 2024/11/1 15:58
* @Version 1.0
*/
public class Bottle implements Packing {
@Override
public String pack() {
return "Bottle";
}
}
- 创建并实现
Item
接口的抽象类,该类提供默认的功能。
/**
* @Description 汉堡抽象类
* @Author gongming.Zhang
* @Date 2024/11/1 16:00
* @Version 1.0
*/
public abstract class Burger implements Item {
@Override
public Packing packing() {
return new Wrapper();
}
@Override
public abstract float price();
}
/**
* @Description 冷饮抽象类
* @Author gongming.Zhang
* @Date 2024/11/1 16:24
* @Version 1.0
*/
public abstract class ColdDrink implements Item {
@Override
public Packing packing() {
return new Bottle();
}
@Override
public abstract float price();
}
- 创建并继承
Burger
和ColdDrink
。
/**
* @Description 鸡肉汉堡实体类
* @Author gongming.Zhang
* @Date 2024/11/1 16:28
* @Version 1.0
*/
public class ChickenBurger extends Burger {
@Override
public String name() {
return "Chicken Burger";
}
@Override
public float price() {
return 50.5f;
}
}
/**
* @Description 素食汉堡实体类
* @Author gongming.Zhang
* @Date 2024/11/1 16:26
* @Version 1.0
*/
public class VegBurger extends Burger {
@Override
public String name() {
return "Veg Burger";
}
@Override
public float price() {
return 25.0f;
}
}
/**
* @Description 可口可乐实体类
* @Author gongming.Zhang
* @Date 2024/11/1 16:28
* @Version 1.0
*/
public class Coke extends ColdDrink {
@Override
public String name() {
return "Coke";
}
@Override
public float price() {
return 30.0f;
}
}
/**
* @Description 百事可乐实体类
* @Author gongming.Zhang
* @Date 2024/11/1 16:30
* @Version 1.0
*/
public class Pepsi extends ColdDrink {
@Override
public String name() {
return "Pepsi";
}
@Override
public float price() {
return 35.0f;
}
}
- 创建一个
Meal
类,表示菜品实体。(产品)
package top.zhang.builderdesignpatterns.entity;
import top.zhang.builderdesignpatterns.entity.food.Item;
import java.util.ArrayList;
import java.util.List;
/**
* @Description 菜品实体类 —— 产品
* @Author gongming.Zhang
* @Date 2024/11/1 16:31
* @Version 1.0
*/
public class Meal {
private List<Item> items = new ArrayList<Item>();
public void addItem(Item item) {
items.add(item);
}
/**
* 获取购买的商品总价
*
* @return 商品总价格
*/
public float getCost() {
float cost = 0.0f;
for (Item item : items) {
cost += item.price();
}
return cost;
}
/**
* 展示购买的商品信息
*
*/
public void showItems() {
for (Item item : items) {
System.out.print("Item : "+item.name());
System.out.print(", Packing : "+item.packing().pack());
System.out.println(", Price : "+item.price());
}
}
}
- 创建一个
MealBuilder
类,实际的builder
类负责创建Meal
对象。(具体建造者)
package top.zhang.builderdesignpatterns.entity;
import top.zhang.builderdesignpatterns.entity.food.entity.ChickenBurger;
import top.zhang.builderdesignpatterns.entity.food.entity.Coke;
import top.zhang.builderdesignpatterns.entity.food.entity.Pepsi;
import top.zhang.builderdesignpatterns.entity.food.entity.VegBurger;
/**
* @Description 负责构建 Meal 对象 —— 具体建造者
* @Author gongming.Zhang
* @Date 2024/11/1 16:34
* @Version 1.0
*/
public class MealBuilder {
/**
* 构建蔬菜餐数据
*
* @return 菜品实体类
*/
public Meal prepareVegMeal() {
Meal meal = new Meal();
meal.addItem(new VegBurger());
meal.addItem(new Coke());
return meal;
}
/**
* 构建非蔬菜餐数据
*
* @return 菜品实体类
*/
public Meal prepareNonVegMeal() {
Meal meal = new Meal();
meal.addItem(new ChickenBurger());
meal.addItem(new Pepsi());
return meal;
}
}
- 测试建造者模式
@SpringBootTest
@RunWith(SpringRunner.class)
class BuilderDesignPatternsApplicationTests {
@Test
public void BuilderPatternDemo() {
MealBuilder mealBuilder = new MealBuilder();
Meal vegMeal = mealBuilder.prepareVegMeal();
System.out.println("Veg Meal");
vegMeal.showItems();
System.out.println("total Cost: " + vegMeal.getCost());
System.out.println("\n\n");
Meal nonVegMeal = mealBuilder.prepareNonVegMeal();
System.out.println("Non-Veg Meal");
nonVegMeal.showItems();
System.out.println("Total Cost: " +nonVegMeal.getCost());
}
}
5. 总结
使用场景:
- 当需要创建一些特定的对象,但是它们拥有共同的组成部分时,比如:一个房子可以由个个部件:框架、墙、窗户等,这些部件可以组合起来构造完整的房子。
- 当对象的构建过程比较复杂且需要多个步骤时,例如,创建一份电子商务订单需要多个步骤,如选择商品、填写地址和支付等,这些步骤可以被分别封装成为订单构建器中的不同方法。
- 当需要创建一些特定类型的对象,例如复杂的数据结构或配置对象时,这在编写配置文件解析器以及通用数据结构如二叉树等时很有用。
- 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。
与抽象工厂模式的区别:
抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。