创建型模式->建造者模式

创建型模式->建造者模式(Builder)

什么是建造者模式

建造者模式是一种创建型设计模式,也叫生成器模式。
定义:封装一个复杂对象构造过程,并允许按步骤构造。

解释:就是将复杂对象的创建过程拆分成多个简单对象的创建过程,并将这些简单对象组合起来构建出复杂对象。

角色组成

产品类(Product): 表示被创建的复杂对象。它通常包含多个部分或者组成,并由具体的建造者逐步构建而成。
抽象建造者类(Builder): 定义了建造复杂对象所需要的各个部分的创建方法。它通常包括多个构建方法和一个返回产品的方法。
具体建造者类(ConcreteBuilder): 实现Builder接口,并提供各个部分或者组成的构建方法。
指挥者类(Director): 负责控制建造者的构建顺序,指挥建造者如何构建复杂对象。

优缺点

优点:

  1. 灵活:可以分步骤地构建复杂对象,使得构建过程更加灵活。

  2. 解耦:可以隔离复杂对象的创建和使用,客户端不必关心对象的创建细节。

  3. 易扩展:增加新的具体建造者很方便,可以扩展构建器功能,符合开闭原则。
    缺点:

  4. 增加工作量:需要额外的代码来创建和管理具体建造者类,增加了程序员的工作量。

  5. 效率低:相比于其他创建型模式,在运行时效率较低,特别是对象太复杂时。

应用场景

生活场景

  • 盒饭套餐:顾客可以选择不同的菜,服务员按照顾客的要求,将这些菜组合起来,最终构建出一个完整的套餐。

Java场景

StringBuilder: 能够动态地构建字符串。
Stream API: 将集合类转为stream流,通过一系列的中间操作和终止操作来生成最终结果。
Lombok的@Builder注解: 一个注解就可以生成建造者模式的代码

代码实现

肯德徳都吃过吧,里面有很多的套餐。假设套餐主要由汉堡、薯条和饮料三种组成,每个组件都有不同种类和大小,并且每个套餐的组合方式也不同。下面以肯德徳套餐为例,解释建造者模式。

产品类: Meal
抽象建造者类: MealBuilder
具体建造者类: BeefBurgerMealBuilder、ChickenMealBuilder、ShrimpMealBuilder
指挥者类: MealDirector

套餐类 (Meal)

java 复制代码
/**
 * @author cris
 * @className Meal
 * @description 套餐产品类
 * @date 2024/06/29 08:11
 **/
@Getter
@Setter
@ToString
public class Meal {
    /**
     * 汉堡
     */
    private String burger;

    /**
     * 薯条
     */
    private String fries;

    /**
     * 饮料
     */
    private String drink;
}

抽象建造者(Builder)

java 复制代码
/**
 * @author cris
 * @className MealBuilder
 * @description 抽象建造者
 * @date 2024/06/29 08:13
 **/
public abstract class MealBuilder {
    protected Meal meal = new Meal();

    /**
     * 构建汉堡
     */
    public abstract void buildBurger();

    /**
     * 构建薯条
     */
    public abstract void buildFries();

    /**
     * 构建饮料
     */
    public abstract void buildDrink();

    public Meal getMeal() {
        return meal;
    }

}

具体构建者 (ConcreteBuilder)

java 复制代码
/**
 * @author cris
 * @className ChickenMealBuilder
 * @description 具体建造者(ConcreteBuilder):鸡肉汉堡套餐
 * @date 2024/06/29 08:16
 **/
public class ChickenMealBuilder extends MealBuilder {
    @Override
    public void buildBurger() {
        meal.setBurger("鸡肉汉堡");
    }

    @Override
    public void buildFries() {
        meal.setFries("中份薯条");
    }

    @Override
    public void buildDrink() {
        meal.setDrink("大杯果汁");
    }
}
java 复制代码
/**
 * @author cris
 * @className BeefMealBuilder
 * @description 具体建造者(ConcreteBuilder):牛肉汉堡套餐
 * @date 2024/06/29 08:18
 **/
public class BeefMealBuilder extends MealBuilder {
    @Override
    public void buildBurger() {
        meal.setBurger("牛肉汉堡");
    }

    @Override
    public void buildFries() {
        meal.setFries("大份薯条");
    }

    @Override
    public void buildDrink() {
        meal.setDrink("大杯可乐");
    }
}
java 复制代码
/**
 * @author cris
 * @className ShrimpMealBuilder
 * @description 具体建造者(ConcreteBuilder):虾肉汉堡套餐
 * @date 2024/06/29 08:19
 **/
public class ShrimpMealBuilder extends MealBuilder {
    @Override
    public void buildBurger() {
        meal.setBurger("虾肉汉堡");
    }

    @Override
    public void buildFries() {
        meal.setFries("小份薯条");
    }

    @Override
    public void buildDrink() {
        meal.setDrink("大杯芬达");
    }
}

指导者 (Director)

java 复制代码
/**
 * @author cris
 * @className MealDirector
 * @description 指导者(Director)
 * @date 2024/06/29 08:21
 **/
public class MealDirector {

    private MealBuilder mealBuilder;

    public void setMealBuilder(MealBuilder mealBuilder) {
        this.mealBuilder = mealBuilder;
    }

    public Meal getMeal() {
        return mealBuilder.getMeal();
    }

    // 制作套餐
    public void constructMeal() {
        mealBuilder.buildBurger();
        mealBuilder.buildFries();
        mealBuilder.buildDrink();
    }
}

测试 (TestBuilder)

java 复制代码
/**
 * @author cris
 * @className TestBuilder
 * @description 测试
 * @date 2024/06/29 08:25
 **/
public class TestBuilder {

    public static void main(String[] args) {
        MealDirector mealDirector = new MealDirector();

        mealDirector.setMealBuilder(new ChickenMealBuilder());
        mealDirector.constructMeal();
        Meal meal1 = mealDirector.getMeal();
        System.out.println("鸡肉汉堡套餐" + meal1.toString());

        mealDirector.setMealBuilder(new BeefMealBuilder());
        mealDirector.constructMeal();
        Meal meal2 = mealDirector.getMeal();
        System.out.println("牛肉汉堡套餐" + meal2.toString());

        mealDirector.setMealBuilder(new ShrimpMealBuilder());
        mealDirector.constructMeal();
        Meal meal3 = mealDirector.getMeal();
        System.out.println("虾肉汉堡套餐" + meal3.toString());
    }
}

总结

使用场景:

  1. 当需要创建一些特定的对象,但是它们拥有共同的组成部分时,比如:一个房子可以由个个部件:框架、墙、窗户等,这些部件可以组合起来构造完整的房子。
  2. 当对象的构建过程比较复杂且需要多个步骤时,例如,创建一份电子商务订单需要多个步骤,如选择商品、填写地址和支付等,这些步骤可以被分别封装成为订单构建器中的不同方法。
  3. 当需要创建一些特定类型的对象,例如复杂的数据结构或配置对象时,这在编写配置文件解析器以及通用数据结构如二叉树等时很有用。
  4. 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。
    与抽象工厂模式的区别:
  • 抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。
相关推荐
hrrrrb20 分钟前
【Java Web 快速入门】九、事务管理
java·spring boot·后端
AirMan1 小时前
深入解析 Spring Caffeine:揭秘 W-TinyLFU 缓存淘汰策略的高命中率秘密
后端
小码编匠2 小时前
C# Bitmap 类在工控实时图像处理中的高效应用与避坑
后端·c#·.net
布朗克1682 小时前
Spring Boot项目通过RestTemplate调用三方接口详细教程
java·spring boot·后端·resttemplate
uhakadotcom3 小时前
使用postgresql时有哪些简单有用的最佳实践
后端·面试·github
IT毕设实战小研3 小时前
基于Spring Boot校园二手交易平台系统设计与实现 二手交易系统 交易平台小程序
java·数据库·vue.js·spring boot·后端·小程序·课程设计
bobz9653 小时前
QT 字体
后端
泉城老铁3 小时前
Spring Boot 中根据 Word 模板导出包含表格、图表等复杂格式的文档
java·后端
用户4099322502123 小时前
如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
后端·github·trae
风象南3 小时前
开发者必备工具:用 SpringBoot 构建轻量级日志查看器,省时又省力
后端