当前位置: 首页 > news >正文

肝一肝设计模式【四】-- 建造者模式

系列文章目录

肝一肝设计模式【一】-- 单例模式 传送门
肝一肝设计模式【二】-- 工厂模式 传送门
肝一肝设计模式【三】-- 原型模式 传送门
肝一肝设计模式【四】-- 建造者模式 传送门


文章目录

  • 系列文章目录
  • 前言
  • 一、什么是建造者模式
  • 二、举个栗子
  • 三、静态内部类写法
  • 四、开源框架中的应用
  • 写在最后


前言

前文中我们知道设计模式可以分为三大类:创建型模式、结构型模式、行为型模式。创建型模式中有5种,前几节里我们分析了单例模式、工厂方法模式、抽象工厂模式、原型模式,那么创建型模式还有最后一种模式:建造者模式,这一节中我们来分析一下建造者模式。


一、什么是建造者模式

建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的对象。
可以这么理解,对象的构建与它的表示分离,就是创建一个对象的实例和成员变量的赋值相分离。建造者模式使用多个简单的对象一步一步构建成一个复杂的对象,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

二、举个栗子

以制作一本儿童绘本为例(默默拿起手边的《白雪公主》┐(・o・)┌ )
在这里插入图片描述
通常绘本由封面、标题、内容、插图、页码来组成,这些内容的组成顺序可以随意调整,我们用建造者模式来模拟一下制作绘本的过程。

写在代码:

@Data
public class Book {private String cover;private String title;private String content;private String pic;private Integer pageNo;@Overridepublic String toString() {return "Book{" +"cover='" + cover + '\'' +", title='" + title + '\'' +", content='" + content + '\'' +", pic='" + pic + '\'' +", pageNo='" + pageNo + '\'' +'}';}
}

然后再建一个建造者类,封装创建过程,由使用者根据需要来调用

public class BookBuilder {private Book book = new Book();public BookBuilder addCover(String cover){book.setCover(cover);return this;}public BookBuilder addTitle(String title){book.setTitle(title);return this;}public BookBuilder addContent(String content){book.setContent(content);return this;}public BookBuilder addPic(String pic){book.setPic(pic);return this;}public BookBuilder addPageNo(Integer pageNo){book.setPageNo(pageNo);return this;}public Book build(){return book;}
}

测试一下

public static void main(String[] args) {BookBuilder builder = new BookBuilder().addCover("漂亮的封面").addTitle("《白雪公主》").addContent("美丽善良的公主被恶毒的皇后嫉妒,被迫逃亡,最终被七个小矮人救助。").addPic("漂亮的插图").addPageNo(30);System.out.println(builder.build());
}

是不是有点熟悉,像不像MyBatis Plus中QueryWrapper的写法,后文我们在开源框架的应用中来具体说一说。

三、静态内部类写法

通常我们更习惯使用静态内部类的方式实现建造者模式,由它负责产品的组装创建,不再需要Builder和Director,这样的话代码结构更加紧凑,创建过程与产品的属性联系更加紧密,同时使得建造者模式的形式更加简洁。

然后我们来修改下代码:

@Data
public class Book {private String cover;private String title;private String content;private String pic;private Integer pageNo;@Overridepublic String toString() {return "Book{" +"cover='" + cover + '\'' +", title='" + title + '\'' +", content='" + content + '\'' +", pic='" + pic + '\'' +", pageNo='" + pageNo + '\'' +'}';}public static class Builder {private Book book = new Book();public BookBuilder addCover(String cover){book.setCover(cover);return this;}public BookBuilder addTitle(String title){book.setTitle(title);return this;}public BookBuilder addContent(String content){book.setContent(content);return this;}public BookBuilder addPic(String pic){book.setPic(pic);return this;}public BookBuilder addPageNo(Integer pageNo){book.setPageNo(pageNo);return this;}public Book build(){return book;}}
}

测试一下

public static void main(String[] args) {Book book = new Book.Builder().addCover("漂亮的封面").addTitle("《白雪公主》").addContent("美丽善良的公主被恶毒的皇后嫉妒,被迫逃亡,最终被七个小矮人救助。").addPic("漂亮的插图").addPageNo(30).build();System.out.println(book);
}

是不是简洁和优雅多了(〃‘▽’〃)

四、开源框架中的应用

刚刚在写样例的时候,有的同学可能已经发现,这种链式写法很像MyBatis Plus的QueryWrapper写法,那么就结合MyBatis Plus这个开源持久层框架的源码,简单来说一说MyBatis Plus是如何基于建造者模式的思想,提供一套流畅的API来构建查询条件的。

由于实际MyBatis Plus源码是很复杂的,我们拿一个简化版的来举例

public class QueryWrapper<T> {private List<String> conditions;public QueryWrapper<T> eq(String column, Object value) {conditions.add(column + " = " + value);return this;}public QueryWrapper<T> ne(String column, Object value) {conditions.add(column + " != " + value);return this;}public QueryWrapper<T> gt(String column, Object value) {conditions.add(column + " > " + value);return this;}// 其他条件方法...public List<T> selectList() {// 根据conditions构建查询语句并执行查询}
}

在这个样例中,QueryWrapper类定义了一系列方法,例如eq、ne、gt等,用于设置不同的查询条件。每个条件方法都返回QueryWrapper对象本身,以便实现链式调用。这里的关键点是在每个条件方法中,都将新的条件添加到conditions列表中,并返回当前对象的引用。

这样我们就可以使用链式调用的方式在一个语句中设置多个查询条件

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John").ne("age", 30).gt("salary", 5000);

这种设计提高了代码的可读性和可维护性,使得构建复杂查询条件变得更加直观和简洁。


写在最后

建造者模式的使用场景:

  • 适用于创建复杂对象,并通过一步步构建对象的方式来隐藏对象构建的细节。

建造者模式的优点:

  • 建造者独立,易扩展。
  • 建造过程可控,便于控制细节风险。
  • 提高代码复用性

建造者模式的缺点

  • 增加了代码复杂性,不易于理解。
  • 对象构建过程固定,不够灵活。

相关文章:

肝一肝设计模式【四】-- 建造者模式

系列文章目录 肝一肝设计模式【一】-- 单例模式 传送门 肝一肝设计模式【二】-- 工厂模式 传送门 肝一肝设计模式【三】-- 原型模式 传送门 肝一肝设计模式【四】-- 建造者模式 传送门 文章目录 系列文章目录前言一、什么是建造者模式二、举个栗子三、静态内部类写法四、开源框…...

从设计到产品

从设计到产品 最近上的一些课的笔记&#xff0c;从 0 开始设计项目的角度去看产品。 设计系统 设计系统(design system) 不是 系统设计(system design)&#xff0c;前者更偏向于 UI/UX 设计部分&#xff0c;后者更偏向于实现部分。 个人觉得&#xff0c;前端开发与 UI/UX 设…...

《疯狂Python讲义》值传递的细节

函数的参数包含着整个程序的规范性&#xff0c;之前还是没有那么去注意重要的细节&#xff0c;读完书中函数值传递篇章&#xff0c;还是有所收获的。 参数有两种形式&#xff0c;一种是形参一种是实参&#xff0c;形参可以理解为实参的载体&#xff0c;函数当中的关键词也是描…...

【7. ROS 中的 IMU 惯性测量单元消息包】

欢迎大家阅读2345VOR的博客【6. 激光雷达接入ROS】&#x1f973;&#x1f973;&#x1f973; 2345VOR鹏鹏主页&#xff1a; 已获得CSDN《嵌入式领域优质创作者》称号&#x1f47b;&#x1f47b;&#x1f47b;&#xff0c;座右铭&#xff1a;脚踏实地&#xff0c;仰望星空&#…...

pcie m.2固态硬盘装机后无法识别到启动盘

1、第一种情况《系统版本过低》 原因&#xff1a; 使用m.2固态硬盘的电脑&#xff0c;最好安装iwn8.1以上的系统&#xff0c;因为win7系统及其win xp系统 没有自带NVME驱动。 搞定办法&#xff1a; 比较简单的方式就是直接开运行快启动u盘启动盘制作工具将系统升级到win10系…...

Java Web应用开发 ——第四章:JavaBean技术测验

一.单项选择题&#xff08;共13题,55.9分&#xff09; 1 在 JSP 中调用 JavaBean 时不会用到的标记是&#xff1a;&#xff08; &#xff09; A、 < jsp:javabean> B、 < jsp:useBean> C、 < jsp:setProperty> D、 < jsp:getProperty> 正确答案&a…...

CTF权威指南 笔记 -第二章二进制文件- 2.4 -动态链接

目录 静态文件的缺点 动态链接 位置无关代码 延迟绑定 _dl_runtime_reslove 函数定义 深入审视 静态文件的缺点 随着可执行文件的增加 静态链接带来的浪费空间问题就会愈发严重 如果大部分可执行文件都需要glibc 那么在链接的时候就需要把 libc.a链接进去 如果一个libc…...

C++:计算机操作系统:多线程:高并发中的线程

高并发中的线程 一切要从CPU说起PC 程序计数器从CPU到操作系统从进程到线程 从这篇开始&#xff0c;我将会开启高性能&#xff0c;高并发系列&#xff0c;本篇是给系列的开篇&#xff0c;主要关注 多线程以及线程池。 一切要从CPU说起 你可能会有疑问&#xff0c;讲多线程为何…...

大数据Doris(十一):Aggregate 数据模型

文章目录 Aggregate 数据模型 一、导入数据聚合 二、保留明细数据...

osg::Drawable类通过setDrawCallback函数设置回调函数的说明

osg::Drawable类可以通过该类的setDrawCallback函数设置回调函数类对象。被设置的回调类对象必须从osg::Drawable::DrawCallback类派生&#xff0c;并重写drawImplementation函数&#xff0c;以实现自己特定的需求。这个回调函数在每次帧事件中都会被调用(如&#xff1a;在帧的…...

Python基础合集 练习17(类与对象)

class Dog: pass papiDog() print(papi) print(type(papi)) 构建方法 创建类过后可以定义一个特殊的方法。在python中构建方法是__init__(),init()必须包含一个self参数 class pig(): #def__init__(self) -> None&#xff1a; print(‘你好’) pipgpig() 属性和方法 cl…...

再多猜一次就爆炸(小黑子误入)

目录 猜数字游戏 游戏设计思路 1.电脑随机生成一个数 2.猜数字 3.输入我是ikun&#xff0c;泰裤辣! 否则电脑将在一分钟后关机 游戏运行效果 源码 代码分析 代码实现关键语句 strcmp() rand()与srand() 时间戳time() 寄语 猜数字游戏 游戏设计思路 1.电脑随机生…...

图像超分辨率简单介绍

文章目录 图像超分辨率简单介绍什么是图像超分辨率&#xff1f;常见的图像超分辨率算法插值算法基于边缘的图像重建算法局部线性嵌入&#xff08;LLE&#xff09;拉普拉斯正则化 基于深度学习的超分辨率算法超分辨率CNN超分辨率GAN 步骤1. 收集数据2. 选择算法3. 训练模型4. 测…...

【Liunx】进程的程序替换——自定义编写极简版shell

目录 进程程序替换[1~5]1.程序替换的接口&#xff08;加载器&#xff09;2.什么是程序替换&#xff1f;3.进程替换的原理4.引入多进程5.系列程序替换接口的详细解析&#xff08;重点&#xff01;&#xff09; 自定义编写一个极简版shell[6~8]6.完成命令行提示符7.获取输入的命令…...

c++标准模板(STL)(std::array)(三)

定义于头文件 <array> template< class T, std::size_t N > struct array;(C11 起 std::array 是封装固定大小数组的容器。 此容器是一个聚合类型&#xff0c;其语义等同于保有一个 C 风格数组 T[N] 作为其唯一非静态数据成员的结构体。不同于 C 风格数组…...

c#笔记-创建一个项目

创建一个项目 创建控制台程序 在你安装完成Visual Studio后打开它&#xff0c;你会的到一个启动窗口 点击创建新项目&#xff0c;选择右上角c#的没有Framework的控制台应用。 项目名称&#xff0c;位置自己随意。 目标框架选择NET7.0。 项目创建完成后应该你的界面应该类似…...

Photoshop如何使用图像调色之实例演示?

文章目录 0.引言1.将一张偏冷调的图像调整成暖调2.将图像调整成不同季节色彩倾向3.变换花朵的颜色4.创建人像轮廓风景5.修饰蓝天白云6.调换花草颜色 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及其配…...

IDEA中使用Git提交代码提示:您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。

IDEA中使用Git提交代码提示&#xff1a;您即将把CRLF行分隔符提交到Gt仓库。 建议将core.autocrlf Git特性设置为trUe,以免发生行分隔符问题。 问题背景&#xff1a; 在IDEA中&#xff0c;使用Git提交代码到远程仓库时&#xff0c;结果弹出一个警告窗口 问题原因&#xff1a; …...

ArduPilot之开源代码LibrarySketches设计

ArduPilot之开源代码Library&Sketches设计 1. 简介1.1 Core libraries1.2 Sensor libraries1.3 Other libraries 2. 源由3. Library Sketches设计3.1 设计框架3.2 Example Sketches3.3 AP_Common Sketches3.3.1 配置sitl环境3.3.2 编译AP_Common3.3.3 运行AP_Common3.3.4 代…...

第一章:概述

1&#xff0c;因特网概述 1.网络、互联网和英特网 网络(Network)由若干结点(Node)和连接这些结点的链路(Link)组成。 多个网络还可以通过路由器互连起来&#xff0c;这样就构成了一个覆盖范围更大的网络&#xff0c;即互联网(或互连网)。因此&#xff0c;互联网是“网络的网络…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...