目录
前言
建造者模式是一种创建型设计模式。用于封装复杂对象的构建过程,通过步骤构建产品类。它包括产品类、抽象建造者、具体建造者和指挥者角色。
优点在于灵活性、解耦和易扩展,缺点是增加工作量和效率较低。适用场景如构建套餐、字符串动态构建、StreamAPI操作等。
1、建造者模式
(Builder Pattern)建造者模式定义:封装一个复杂对象构造过程,并允许按步骤构造。
将一个复杂对象的构建(如何分步组装)和其表示(最后生成的产品)分离。使同样的构建过程可以创建不同表现(参数组合)的对象。
- 针对复杂对象,构建流程有“步骤”,可以按需改变每一步内容或顺序
- 最终可以生成不同个性化的产物(同样流程,不同参数或细节)
2、建造者模式结构
如下所示:
- Product(产品类):最终要建造的复杂对象。
- Builder(抽象建造者):定义构建产品各部分的接口。
- ConcreteBuilder(具体建造者):实现 Builder 接口,每步怎么造。
- Director(指挥者):决定调用哪些步骤,以及什么顺序,控制“组装流程”。
3、实现
假设建造一个定制汉堡(面包、肉、蔬菜、酱料等均可变),可以有不同套餐。
1. 产品类
class Burger {
private String bread;
private String meat;
private String vegetable;
private String sauce;
// setter/getter略
@Override
public String toString() {
return "Burger{" +
"bread='" + bread + '\'' +
", meat='" + meat + '\'' +
", vegetable='" + vegetable + '\'' +
", sauce='" + sauce + '\'' +
'}';
}
}
2. 抽象建造者
interface BurgerBuilder {
BurgerBuilder chooseBread(String bread);
BurgerBuilder chooseMeat(String meat);
BurgerBuilder chooseVegetable(String vegetable);
BurgerBuilder chooseSauce(String sauce);
Burger build();
}
3. 具体建造者
class DefaultBurgerBuilder implements BurgerBuilder {
private Burger burger = new Burger();
@Override
public BurgerBuilder chooseBread(String bread) {
burger.setBread(bread);
return this;
}
@Override
public BurgerBuilder chooseMeat(String meat) {
burger.setMeat(meat);
return this;
}
@Override
public BurgerBuilder chooseVegetable(String vegetable) {
burger.setVegetable(vegetable);
return this;
}
@Override
public BurgerBuilder chooseSauce(String sauce) {
burger.setSauce(sauce);
return this;
}
@Override
public Burger build() {
return burger;
}
}
4. 指挥者 Director(可选)
如果产品组合很复杂,可以有个指挥者预设“套餐”:
class BurgerDirector {
public Burger createCheeseBeefBurger(BurgerBuilder builder) {
return builder.chooseBread("芝麻面包")
.chooseMeat("牛肉")
.chooseVegetable("生菜")
.chooseSauce("芝士酱")
.build();
}
// 也可有 createSpicyChickenBurger() ...
}
5. 客户端使用
public class TestBuilder {
public static void main(String[] args) {
BurgerBuilder builder = new DefaultBurgerBuilder();
// 自定义装配
Burger burger = builder
.chooseBread("全麦")
.chooseMeat("鸡肉")
.chooseVegetable("番茄")
.chooseSauce("千岛酱")
.build();
System.out.println(burger);
// 使用预定义指挥者装配套餐
BurgerDirector director = new BurgerDirector();
Burger cheeseBurger = director.createCheeseBeefBurger(new DefaultBurgerBuilder());
System.out.println(cheeseBurger);
}
}
结果输出:
Burger{bread='全麦', meat='鸡肉', vegetable='番茄', sauce='千岛酱'}
Burger{bread='芝麻面包', meat='牛肉', vegetable='生菜', sauce='芝士酱'}
4、工厂模式对比
特点:
- 创建对象时,一次性指定参数,直接new或工厂create返回对象
- 不能灵活分步骤定制产物,组合变化很局限
- 适合产品结构简单、参数少、变化小的“快速生产”
简单工厂/工厂方法代码:
// 简单工厂
class BurgerFactory {
public static Burger createCheeseBurger() {
Burger b = new Burger();
b.setBread("芝麻面包");
b.setMeat("牛肉");
b.setVegetable("生菜");
b.setSauce("芝士酱");
return b;
}
public static Burger createChickenBurger() { ... }
}
// 使用
Burger burger = BurgerFactory.createCheeseBurger();
对比:
- 工厂模式:侧重产物种类,比如“要A还是B”,流程和细节厂内规定死了,客户端改不了。
- 建造者模式:侧重“每一步都能自由定制和变化”,组装细节自己掌握,可以一个build流程装不同产品,还能链式调用、流式风格。
5、适用场景差异
如下所示:
1、Lombok的@Builder注解
支持链式建造大对象。
2、StringBuilder/StringBuffer
3、MyBatis的SqlSessionFactoryBuilder
4、复杂业务DTO装配,配置文件装配器
5、Stream API:
将集合类转为stream流,通过一系列的中间操作和终止操作来生成最终结果。
总结
1、建造者模式适用于:
复杂对象的*组装、参数变化多、“按步构建”*的场景,强调流程可扩展、定制化强。
2、工厂模式适用于:
产品类目变化,强调“要什么生产什么”,但组装流程是固定的、透明的。
参考文章: