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

创建型模式->建造者模式(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. 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。
    与抽象工厂模式的区别:
  • 抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。
相关推荐
容若只如初见3 小时前
项目实战--Spring Boot + Minio文件切片上传下载
java·spring boot·后端
码农爱java3 小时前
Spring Boot 中的监视器是什么?有什么作用?
java·spring boot·后端·面试·monitor·监视器
Apifox.4 小时前
什么是 HTTP POST 请求?初学者指南与示范
后端·http·学习方法·web
无名指的等待7125 小时前
SpringBoot实现图片添加水印(完整)
java·spring boot·后端
甜甜圈的小饼干8 小时前
Spring Boot+Vue项目从零入手
vue.js·spring boot·后端
我曾遇到一束光9 小时前
Spring boot 更改启动LOGO
数据库·spring boot·后端
tiger_angel9 小时前
springboot集成gzip和zip数据压缩传输-满足2k数据自动压缩(适用大数据信息传输)
大数据·spring boot·后端·数据压缩·压缩数据·压缩传输消息
笔触狂放10 小时前
【Django】网上蛋糕项目商城-关键字搜索,商品详情功能
后端·python·django
q5673152310 小时前
Python 3.x 下的 3D 游戏引擎
开发语言·后端·python·3d·django·游戏引擎
奋斗的袍子00711 小时前
SpringBoot:SpringBoot统一响应和统一异常处理
java·spring boot·后端·spring·统一异常处理·统一响应·自定义异常