4、设计模式之建造者模式(Builder)

news2024/11/20 15:17:36

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

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

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

二、角色组成

产品类(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());
    }
}

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

六、总结
使用场景:

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

吴恩达机器学习-可选实验室:逻辑回归,决策边界(Logistic Regression,Decision Boundary))

文章目录 目标数据集图数据逻辑回归模型复习逻辑回归和决策边界绘图决策边界恭喜 目标 在本实验中,你将:绘制逻辑回归模型的决策边界。这会让你更好地理解模型的预测。 import numpy as np %matplotlib widget import matplotlib.pyplot as plt from lab_utils_co…

Python逆向:pyc字节码转py文件

一、 工具准备 反编译工具:pycdc.exe 十六进制编辑器:010editor 二、字节码文件转换 在CTF中,有时候会得到一串十六进制文件,通过010editor使用查看后,怀疑可能是python的字节码文件。 三、逆向反编译 将010editor得到…

【网络工程师进阶之路】BFD技术

个人名片:🪪 🐼作者简介:一名大三在校生,喜欢AI编程🎋 🐻‍❄️个人主页🥇:落798. 🐼个人WeChat:hmmwx53 🕊️系列专栏:&a…

第十四届蓝桥杯蜗牛

蜗牛 线性dp 目录 蜗牛 线性dp 先求到达竹竿底部的状态转移方程 求蜗牛到达第i根竹竿的传送门入口的最短时间​编辑 题目链接:蓝桥杯2023年第十四届省赛真题-蜗牛 - C语言网 关键在于建立数组将竹竿上的每个状态量表示出来,并分析出状态转移方程 in…

《详解:鸿蒙NEXT开发核心技术》

我们现在都知道鸿蒙作为一个国产的全栈自研系统,经过国家主推后。已经引起人们很大的关注,其中作为开发者来说;许多一线大厂已经与其华为鸿蒙展开原生应用的合作了,目前了解到已经有200家。而之后出现了很多的高薪鸿蒙开发岗位&am…

Unity制作马赛克效果

大家好,我是阿赵。   之前在玩怒之铁拳4里面,看到了马赛克场景转换的效果,觉得很有趣,于是也来做一下。 一、2D版本的马赛克转场效果 先看看视频效果: 马赛克转场 这里我是直接写shader实现的,我这里是把…

sqlite3——数据库——day2

今天学习了sqlite3数据库 sqlite3_open sqlite3_openint sqlite3_open(const char *filename, /* Database filename (UTF-8) */sqlite3 **ppDb /* OUT: SQLite db handle */); 功能:打开数据库文件(创建一个数据库连接) 参数:filename:数据库文件路径 ppDb:操作数…

SpringCloud Gateway 新一代网关

一、前言 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第六篇,即介绍 Gateway 新一代网关。 二、概述 2.1 Gateway 是什么 Gateway 是在 Spring 生…

前端请求到 SpringMVC 的处理流程

1. 发起请求 客户端通过 HTTP 协议向服务器发起请求。 2. 前端控制器(DispatcherServlet) 这个请求会先到前端控制器 DispatcherServlet,它是整个流程的入口点,负责接收请求并将其分发给相应的处理器。 3. 处理器映射&#xf…

安卓项目:app注册/登录界面设计

目录 第一步:设计视图xml 第二步:编写登录和注册逻辑代码 运行效果展示: 总结: 提前展示项目结构: 第一步:设计视图xml 在layout目录下面创建activity_login.xml和activity_main.xml文件 activity_lo…

rust学习(手动写一个线程池)

哈哈&#xff0c;主要是为了练习一下rust的语法&#xff0c;不喜勿喷。 一.Executor申明 struct AExecutor<T> {results:Arc<Mutex<HashMap<u32,T>>>, //1functions:Arc<Mutex<Vec<ATask<T>>>> //2 } 1.results&#xff1a…

docker-compose up -d使用遇到问题no configuration file provided: not found

docker-compose up -d使用遇到问题&#xff0c;因为你文件名称没指定&#xff0c; 又找不到默认的文件名称&#xff1b;如果该目录下有个文件叫docker-compose.yml时&#xff0c;那么可以直接使用docker-compose up -d;否则就要使用docker-compose -f mysql up -d

IP数据报格式

每一行都由32位比特&#xff0c;即4个字节组成&#xff0c;每个格子称为字段或者域。IP数据报由20字节的固定部分和最大40字节的可变部分组成。 总长度 总长度为16个比特&#xff0c;该字段的取值以字节为单位&#xff0c;用来表示IPv4数据报的长度(首部长度数据载荷长度)最大…

【阿里云系列】-基于云效构建部署Springboot项目到ACK

介绍 为了提高项目迭代的速度加速交付产品给客户&#xff0c;我们通常会选择CICD工具来减少人力投入产生的成本&#xff0c;开源的工具比如有成熟的Jenkins&#xff0c;但是本文讲的是阿里云提高的解决方案云效平台&#xff0c;通过配置流水线的形式实现项目的快速部署到服务器…

(第73天)DBUA 升级:单机 11GR2 升级到 19C

前言 Oracle 11GR2 版本是上一个长期稳定版本,但是官方已与 2020 年停止服务,官方建议升级到最新长期稳定版 19C。 参考官方文档:当前数据库版本的发行时间表 (Doc ID 1626244.1) Database Upgrade Assistant (DBUA) 交互式的引导我们完成升级数据库的步骤,它会自动执行为…

前端去除网页水印

按F12&#xff0c;打开开发者工具面板&#xff0c;然后直接在样式搜索backgroud 然后直接取消backgroud 的复选框即可。

每天五分钟计算机视觉:图像数据不足带来的问题和解决办法

本文重点 在当今的数字时代,图像数据的应用已经渗透到各个领域,包括但不限于计算机视觉、机器学习、自动驾驶、医疗诊断等。然而,当图像数据不足时,会引发一系列问题,对相关应用产生负面影响。 尤其是计算机视觉领域,图像数据尤为珍贵和稀缺,如果计算机视觉的任务中,如…

Linux本地搭建FastDFS系统

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…

Git版本工具学习

目录 版本控制git配置工作区域文件状态git对象模型基础命令.gitignore忽略文件IDEA集成Git 版本控制 本地版本控制&#xff1a;在本地记录每一次版本更新。 集中版本控制&#xff1a;版本数据都保存在单一服务器&#xff0c;不联网就看不到版本信息。SVN 分布式版本控制&…

漏洞发现-漏扫项目篇武装BURP浏览器插件信息收集分析辅助

知识点 1、插件类-武装BurpSuite-漏洞检测&分析辅助 2、插件类-武装谷歌浏览器-信息收集&情报辅助 章节点&#xff1a; 漏洞发现-Web&框架组件&中间件&APP&小程序&系统 扫描项目-综合漏扫&特征漏扫&被动漏扫&联动漏扫 Poc开发-Ymal语…