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

创建型模式->建造者模式(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. 建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。
    与抽象工厂模式的区别:
  • 抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。
相关推荐
全栈派森40 分钟前
云存储最佳实践
后端·python·程序人生·flask
CircleMouse1 小时前
基于 RedisTemplate 的分页缓存设计
java·开发语言·后端·spring·缓存
獨枭2 小时前
使用 163 邮箱实现 Spring Boot 邮箱验证码登录
java·spring boot·后端
维基框架2 小时前
Spring Boot 封装 MinIO 工具
java·spring boot·后端
秋野酱2 小时前
基于javaweb的SpringBoot酒店管理系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
☞无能盖世♛逞何英雄☜2 小时前
Flask框架搭建
后端·python·flask
进击的雷神3 小时前
Perl语言深度考查:从文本处理到正则表达式的全面掌握
开发语言·后端·scala
进击的雷神3 小时前
Perl测试起步:从零到精通的完整指南
开发语言·后端·scala
豌豆花下猫4 小时前
Python 潮流周刊#102:微软裁员 Faster CPython 团队(摘要)
后端·python·ai
秋野酱4 小时前
基于javaweb的SpringBoot驾校预约学习系统设计与实现(源码+文档+部署讲解)
spring boot·后端·学习