4、设计模式之建造者模式

一、什么是建造者模式
建造者模式是一种创建型设计模式,也叫生成器模式。

定义:封装一个复杂对象构造过程,并允许按步骤构造。

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

二、角色组成

产品类(Product):表示被创建的复杂对象。它通常包含多个部分或者组成,并由具体的建造者逐步构建而成。

抽象建造者类(Builder):定义了建造复杂对象所需要的各个部分的创建方法。它通常包括多个构建方法和一个返回产品的方法。

具体建造者类(ConcreteBuilder):实现Builder接口,并提供各个部分或者组成的构建方法。

指挥者类(Director):负责控制建造者的构建顺序,指挥建造者如何构建复杂对象。

三、优缺点
优点:

灵活:可以分步骤地构建复杂对象,使得构建过程更加灵活。
解耦:可以隔离复杂对象的创建和使用,客户端不必关心对象的创建细节。
易扩展:增加新的具体建造者很方便,可以扩展构建器功能,符合开闭原则。
缺点:

增加工作量:需要额外的代码来创建和管理具体建造者类,增加了程序员的工作量。
效率低:相比于其他创建型模式,在运行时效率较低,特别是对象太复杂时。
四、应用场景
4.1 生活场景
盒饭套餐:顾客可以选择不同的菜,服务员按照顾客的要求,将这些菜组合起来,最终构建出一个完整的套餐。
盖房子:需要分多个阶段进行,比如准备材料、打地基、盖围墙…。建造者模式可以将房屋的建造分解成多个步骤,每个步骤对应一个具体的建造者,最终由包工头(指导者)来调用不同的建造者,完成整个房子的建造。
4.2 java场景

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

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

产品类:Meal

抽象建造者类:MealBuilder

具体建造者类:BeefBurgerMealBuilder、ChickenMealBuilder、ShrimpMealBuilder

指挥者类:MealDirector

在这里插入图片描述
5.1 产品类(Product)

/**
 * 
 * 1.产品类(Product)
 */
@Data
public class Meal {
 
    //汉堡包
    private String burger;
 
    //薯条
    private String fries;
 
    //饮料
    private String drink;
}

5.2 抽象建造者(Builder)

/**
 * 
 * 2.抽象建造者(Builder)
 */
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;
    }
}

5.3 具体构建者(ConcreteBuilder)

/**
 *
 * 3.具体建造者(ConcreteBuilder):鸡肉汉堡套餐
 */
public class ChickenMealBuilder extends MealBuilder{
    @Override
    public void buildBurger() {
        meal.setBurger("鸡肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("中份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("大杯果汁");
    }
}
/**
 * 
 * 3.具体建造者(ConcreteBuilder):牛肉汉堡套餐
 */
public class BeefBurgerMealBuilder extends MealBuilder {
 
    @Override
    public void buildBurger() {
        meal.setBurger("牛肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("大份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("中杯可乐");
    }
}

/**
 * 
 * 3.具体建造者(ConcreteBuilder):虾肉汉堡套餐
 */
public class ShrimpMealBuilder extends MealBuilder {
    @Override
    public void buildBurger() {
        meal.setBurger("虾肉汉堡");
    }
 
    @Override
    public void buildFries() {
        meal.setFries("小份薯条");
    }
 
    @Override
    public void buildDrink() {
        meal.setDrink("大杯芬达");
    }
}

5.4 指导者(Director)


/**
 * 
 * 4.指导者(Director)
 */
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();
    }
}

5.5 testBuilder

/**
 * 
 * 建造者模式测试类
 */
@SpringBootTest
public class TestBuilder {
 
    @Test
    void testBuilder(){
        //创建指导者
        MealDirector director=new MealDirector();
 
        //执导建造牛肉套餐
        director.setMealBuilder(new BeefBurgerMealBuilder());
        director.constructMeal();
        Meal meal = director.getMeal();
        System.out.println("牛肉套餐:"+meal.toString());
 
        //鸡肉套餐
        director.setMealBuilder(new ChickenMealBuilder());
        director.constructMeal();
        Meal meal2 = director.getMeal();
        System.out.println("鸡肉套餐:"+meal2.toString());
 
        //虾肉套餐
        director.setMealBuilder(new ShrimpMealBuilder());
        director.constructMeal();
        Meal meal3 = director.getMeal();
        System.out.println("虾肉套餐:"+meal3.toString());
    }
}

根据不同的需求,建造者模式可以构造出不同的套餐对象。每个套餐的构建过程都由不同的建造者实现,在构建过程中可定制相应的属性。最终,因为套餐的构建过程和表示分离,所以同样的构建过程可以创建出不同的表示。

六、总结
使用场景:

当需要创建一些特定的对象,但是它们拥有共同的组成部分时,比如:一个房子可以由个个部件:框架、墙、窗户等,这些部件可以组合起来构造完整的房子。
当对象的构建过程比较复杂且需要多个步骤时,例如,创建一份电子商务订单需要多个步骤,如选择商品、填写地址和支付等,这些步骤可以被分别封装成为订单构建器中的不同方法。
当需要创建一些特定类型的对象,例如复杂的数据结构或配置对象时,这在编写配置文件解析器以及通用数据结构如二叉树等时很有用。
建造者模式也可以被用于通过更高级的方式来构建复杂对象,例如:序列化和反序列化。
与抽象工厂模式的区别:

抽象工厂模式强调的是产品族的创建,即相关的产品一起被创建出来,而建造者模式强调的是一个复杂对象的创建,即它的各个部分逐步被创建出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/452630.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大路灯有必要买吗?测评师推荐五大大路灯品牌!

不知道各位家长有没有发现,近几年来小小年纪就戴眼镜的孩子真的越来越多了! 根据专家数据统计,在全国青少年近视率中小学生就占其40%比重,也代表了10个学生中就有4、5个是戴眼镜的。造成这个趋势的原因也不难理解,一是…

Prometheus 安装部署

文章目录 1.部署Prometheus1.1.修改配置文件1.2.配置告警规则1.3.运行Docker 2.部署Alertmanager2.1.修改配置文件2.2.Prometheus监控配置2.3.运行Docker 3.部署Grafana3.1.运行Docker3.2. 配置数据源3.3. 配置dashboard 开源中间件 # Prometheushttps://iothub.org.cn/docs/m…

MATLAB中格式化文本处理

目录 格式化操作符的字段 转换字符 子类型 精度 字段宽度 标志 值标识符 特殊字符 设置字段宽度和精度 精度和字段宽度的格式化规则 在格式设定符外部指定字段宽度和精度 在宽度和精度字段中指定带编号的标识符 使用标识符的限制 要将数据转换为文本并控制其格式&…

【AnaConda/MiniConda/Linux】使用sudo python或切换root管理员conda环境被绕过解决方案

写在前面 部分机型修改环境变量存在风险,可能用于被覆盖而出现大量命令无法找到的情况 可以输入这个解决 export PATH/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin往期相关内容 探索Miniconda3:简单、灵活的Python环境和…

【线代基础】张量、向量、标量、矩阵的区别

1、标量(Scalar) 纯数字,无方向性、无维度概念。因此也叫 标量张量、零维张量、0D张量 例如,x18,x21.34 x1、x2即为标量 2、张量(tensor) 具有方向性,可以理解为一个多维数组&a…

相机模型Omnidirectional Camera(全方位摄像机)

1. 背景 大多数商用相机都可以描述为针孔相机,通过透视投影进行建模。然而,有些投影系统的几何结构无法使用传统针孔模型来描述,因为成像设备引入了非常高的失真。其中一些系统就是全方位摄像机。 有几种方法可以制作全向相机。屈光照相机(D…

《手把手教你》系列技巧篇(三十二)-java+ selenium自动化测试-select 下拉框(详解教程)

1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助。 2.select 下拉框 2.1Select类 1.在Selenium中,针对html的标签sel…

工科硕士研究生毕业论文撰写总结

工科硕士研究生毕业论文撰写总结 最近一段看了十几篇研究生毕业论文,发现不少问题。结合最近几年当评委及审论文的经验来总结下工科硕士研究生毕业论文撰写毕业论文问题与经验。 一.科技论文的总要求 论文是写给同行看的,注意读者对象。&a…

细粒度IP定位参文27(HGNN):Identifying user geolocation(2022年)

[27] F. Zhou, T. Wang, T. Zhong, and G. Trajcevski, “Identifying user geolocation with hierarchical graph neural networks and explainable fusion,” Inf. Fusion, vol. 81, pp. 1–13, 2022. (用层次图、神经网络和可解释的融合来识别用户的地理定位) 论文地址:…

十四、软考-系统架构设计师笔记-云原生架构设计理论与实践

1、云原生架构背景 云原生架构定义 从技术的角度,云原生架构是基于云原生技术的一组架构原则和设计模式的集合,旨在将云应用中的非业务代码部分进行最大化的剥离,从而让云设施接管应用中原有的大量非功能特性(如弹性、韧性、安全、可观测性、…

趣学前端 | JavaScript标准库

背景 最近睡前习惯翻会书,重温了《JavaScript权威指南》这本书。这本书,文字小,内容多。两年了,我才翻到第十章。因为书太厚,平时都充当电脑支架。 JavaScript标准库 今天阅读的章节是JavaScript标准库,…

【Kimi帮我看论文(四)】TransE:Translating Embeddings for Modeling Multi-relational Data

一、论文信息 1 标题 Translating Embeddings for Modeling Multi-relational Data 2 作者 Antoine Bordes, Nicolas Usunier, Alberto Garcia-Durn, Jason Weston, Oksana Yakhnenko 3 研究机构 Universit de Technologie de Compigne – CNRS Heudiasyc UMR 7253 Compi…

C# SM2加解密 ——国密SM2算法

SM2 是国家密码管理局组织制定并提出的椭圆曲线密码算法标准。 本文使用第三方密码库 BouncyCastle 实现 SM2 加解密,使用 NuGet 安装即可,包名:Portable.BouncyCastle,目前最新版本为:1.9.0。 using Org.BouncyCastl…

Docker部署黑马商城项目笔记

部署后端 创建mysql目录如下,上传对应的文件 运行以下命令 docker run -d \--name mysql \-p 3306:3306 \-e TZAsia/Shanghai \-e MYSQL_ROOT_PASSWORD123 \-v ./mysql/data:/var/lib/mysql \-v ./mysql/conf:/etc/mysql/conf.d \-v ./mysql/init:/docker-entry…

swagger踩坑之请求类不显示具体字段

swagger踩坑之请求类不显示具体字段 省流:枚举字段需要加上ApiModelProperty注解 过程复现: TestEnum 枚举不加注解,swagger的UI类不显示详细字段 Data Accessors(chain true) ApiModel(value "test对象", description &quo…

管理交换机

文章目录 本地管理交换机物理交换机如何本地管理ensp上的虚拟交换机如何本地管理认证模式的三种方式 远程管理交换机配置通过Telnet登录设备配置通过STelnet登录设备 --推荐的方式检查配置结果使用Cloud管理多个交换机时 华为官网配置信息 本地管理交换机 当交换机首次使用时&…

语音合成技术:从概念到应用的全面解析

目录 前言1 语音合成技术简介2 技术解析2.1 语音合成的基本流程2.2 传统语音合成技术2.3 基于深度学习的语音合成 3 语音合成技术应用3.1 虚拟助手与聊天机器人3.2 无障碍通信3.3 语言学习3.4 媒体和娱乐 4 语音合成技术的挑战4.1 自然性的提升4.2 情感表达的深化4.3 多样性与包…

Docker自建蜜罐系统【失陷检测、外网威胁感知、威胁情报】

项目地址: https://hfish.net Hfish是一款基于Docker的网络钓鱼平台,它能够帮助安全团队模拟各种网络钓鱼攻击,以测试和提高组织的安全防御能力。 Hfish的优点 为什么选择Hfish? 蜜罐通常被定义为具有轻量级检测能力、低误报率…

【3GPP】【核心网】【5G】NG接口介绍(超详细)

目录 1. NG接口定义 2. 接口原则和功能 3. NG 接口控制面 5. NG接口主要信令流程 6. NG SETUP过程 1. NG接口定义 NG接口指无线接入网与5G核心网之间的接口。在5G SA网络中,gNB之间通过Xn接口进行连接,gNB与5GC之间通过NG接口进行连接。NG接口分为NG-C接口和NG…

O2OA开发的新版考勤管理

O2OA(翱途)开发平台对考勤管理重新进行了开发,全新的版本更好用,更直观。 考勤管理对员工的工作出勤情况进行记录、分析和报告的过程。它是对员工工作表现评估的重要依据,也是企业管理中的重要组成部分。考勤管理包括对员工的工作时间、迟到…