java设计模式-生成器模式
文章目录
- 生成器模式(Builder)
- 1、目的和适用场景
- 2、角色和职责
- 3、实现步骤
- 4、示例1
- 5、示例2
- 6、优点
- 7、示例场景
生成器模式(Builder)
生成器模式(Builder Pattern)是一种创建型设计模式,它用于构造一个复杂对象的步骤分离。这样可以使用相同的构建过程创建不同的表示。生成器模式通常用于解决当一个对象需要多个部分来一步步构建时,直接实例化对象会导致构造方法过于复杂,参数列表过长的问题。使用生成器模式可以使对象的构建过程和表示分离,允许用户只通过指定复杂对象的类型和内容就可以构建它们,隐藏了对象的内部结构和构建过程。
1、目的和适用场景
生成器模式的主要目的是将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式特别适用于以下场景:
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
2、角色和职责
- 产品(Product):最终要创建的对象,通常包含多个组成部分。
- 生成器(Builder):定义创建产品对象所需的所有操作的接口或抽象类。
- 具体生成器(Concrete Builder):实现Builder接口的类,提供构建产品的具体实现。它负责创建产品对象的各个部分,并记录产品各部分的构造过程。
- 指导者(Director):负责安排已有模块的构造步骤,不涉及具体产品信息,只负责保证对象各部分完整创建或按某种顺序创建。
- 客户端(Client):使用生成器模式的地方,它将指导者和具体生成器关联起来,以创建复杂对象。
3、实现步骤
- 定义产品类:创建一个包含多个组成部件的复杂对象。
- 定义生成器接口:声明在所有类型生成器中通用的产品构造步骤。
- 实现具体生成器:为创建一个特定的产品变体提供实现。
- 定义指导者类:定义调用构建步骤的顺序来创建产品的方法。
- 客户端代码:创建一个生成器对象,将其传递给指导者,然后初始化构造过程。最后,从生成器对象中获取最终结果。
4、示例1
考虑一个简单的例子,我们需要创建一个文档对象,它可能包括标题、正文、图像等部分。我们可以使用生成器模式来灵活构造各种文档。
// 产品类
public class Document {private String title;private String body;private List<String> images = new ArrayList<>();public void setTitle(String title) {this.title = title;}public void setBody(String body) {this.body = body;}public void addImage(String image) {images.add(image);}public void showDocument() {System.out.println("Document Title: " + title);System.out.println("Body: " + body);System.out.println("Images: " + String.join(", ", images));}
}// 抽象生成器
public interface DocumentBuilder {void buildTitle(String title);void buildBody(String body);void buildImage(String image);Document getDocument();
}// 具体生成器
public class ConcreteDocumentBuilder implements DocumentBuilder {private Document document = new Document();@Overridepublic void buildTitle(String title) {document.setTitle(title);}@Overridepublic void buildBody(String body) {document.setBody(body);}@Overridepublic void buildImage(String image) {document.addImage(image);}@Overridepublic Document getDocument() {return document;}
}// 指导者
public class Director {private DocumentBuilder builder;public Director(DocumentBuilder builder) {this.builder = builder;}public void construct(String title, String body, List<String> images) {builder.buildTitle(title);builder.buildBody(body);for (String image : images) {builder.buildImage(image);}}
}// 客户端
public class Client {public static void main(String[] args) {DocumentBuilder builder = new ConcreteDocumentBuilder();Director director = new Director(builder);List<String> images = Arrays.asList("Image1", "Image2");director.construct("My Title", "This is the body.", images);Document document = builder.getDocument();document.showDocument();}
}
在这个例子中,ConcreteDocumentBuilder类实现了DocumentBuilder接口,提供了构建Document对象各个部分的
5、示例2
假设我们需要构建一个复杂的Car对象,它包含engine, seats, GPS等多个部分。
// 产品类
public class Car {private String engine;private int seats;private boolean GPS;// Car的构造器/Setter略去,提供设置各个属性的方法
}// 生成器接口
public interface Builder {void setEngine(String engine);void setSeats(int seats);void setGPS(boolean GPS);
}// 具体生成器
public class CarBuilder implements Builder {private Car car;public CarBuilder() {this.car = new Car();}@Overridepublic void setEngine(String engine) {car.setEngine(engine);}@Overridepublic void setSeats(int seats) {car.setSeats(seats);}@Overridepublic void setGPS(boolean GPS) {car.setGPS(GPS);}public Car build() {return car;}
}// 指导者
public class Director {public void constructSportsCar(Builder builder) {builder.setEngine("Sport Engine");builder.setSeats(2);builder.setGPS(true);}// 可以定义更多constructXxxCar方法以构建不同类型的汽车
}// 客户端代码
public class Demo {public static void main(String[] args) {CarBuilder builder = new CarBuilder();Director director = new Director();// 指导者使用具体生成器实例进行构建操作director.constructSportsCar(builder);// 从生成器中获取最终构建的产品Car car = builder.build();System.out.println(car);}
}
6、优点
- 封装性好:客户端不需要知道产品内部组成的细节。
- 构建和表示分离:构建算法可以独立于产品的组成部分以及它们的装配方式。
- 更好的复用性:由于构建过程被封装在指导
生成器(Builder)模式的使用场景主要集中在需要构建一个复杂对象时,特别是当这个对象的构造过程需要多个步骤,或者构造参数很多,而且许多参数具有默认值。具体的应用场景包括:
- 分离复杂对象的构造和表示
当创建复杂对象的过程一致,但对象的内部表示可能变化时,生成器模式提供了非常灵活的解决方案。通过相同的构建过程可以创建不同的表示。 - 控制复杂对象的构造过程
生成器模式将一个复杂对象的构造过程封装在其对应的生成器中,使得这个构造过程被局部化,且可以被重复使用。这样做还能使构造代码与表示代码分离,降低系统的耦合度。 - 参数过多的对象创建
对于一个参数数量很多的对象,尤其是大多数参数都有默认值时,使用传统的构造函数会非常繁琐。生成器模式允许客户端仅通过必需的参数构造对象,并通过链式调用方式设置其他可选参数。 - 需要构建的对象应具有不同的变体,而不是重载大量构造函数
当一个类需要大量的构造函数,参数组合较多时,使用生成器模式可以避免构造函数过多,使得构造过程更清晰。 - 创建复合对象
复合对象是指那些包含其他对象的对象。对于这样的对象,使用生成器模式可以先创建其包含的对象,然后再按照一定的步骤和顺序构造复合对象。
7、示例场景
- 文本转换器:将一个文档转换成多种格式,例如HTML、纯文本或者RTF格式。每种转换器都可以作为一个具体的生成器,而文档的读取过程则是统一的。
- 用户界面构建器:在GUI应用程序中,可能需要创建复杂的用户界面。生成器模式可以逐步构建用户界面的各个部分,如菜单、工具栏、按钮等,最后组合成完整的用户界面。
- SQL查询构造器:用于构建复杂的SQL查询,允许动态添加不同的条件、选择字段、设置排序规则等,最后生成完整的SQL语句。
生成器模式通过将对象的构造过程从其表示中分离,使得相同的构建过程可以创建不同的表示,为复杂对象的创建提供了更高的灵活性和控制力。
相关文章:
java设计模式-生成器模式
文章目录 生成器模式(Builder)1、目的和适用场景2、角色和职责3、实现步骤4、示例15、示例26、优点7、示例场景 生成器模式(Builder) 生成器模式(Builder Pattern)是一种创建型设计模式,它用于…...
《前端面试题》- TypeScript - TypeScript的优/缺点
问题 简述TypeScript的优/缺点 答案 优点 增强了代码的可读性和可维护性包容性,js可以直接改成ts,ts编译报错也可以生成js文件,兼容第三方库,即使不是ts编写的社区活跃,完全支持es6 缺点 增加学习成本增加开发成…...

微服务---feign调用服务
目录 Feign简介 Feign的作用 Feign的使用步骤 引入依赖 具体业务逻辑 配置日志 在其它服务中使用接口 接着上一篇博客,我们讲过了nacos的基础使用,知道它是注册服务用的,接下来我们我们思考如果一个服务需要调用另一个服务的接口信息&…...
刷题笔记 - 滑动窗口
文章目录 滑动窗口最长无重复子串最小覆盖子串串联所有单词的子串长度最小的子数组滑动窗口最大值字符串的排列最小区间 滑动窗口 所有题目来自leetcode的回答:https://leetcode.cn/problems/longest-substring-without-repeating-characters/solutions/3982/hua-d…...

Docker搭建LNMP+Wordpress的实验
目录 一、项目的介绍 1、项目需求 2、服务器环境 3、任务需求 二、Linux系统基础镜像 三、部署Nginx 1、建立工作目录 2、编写Dockerfile 3、准备nginx.conf配置文件 4、设置自定义网段和创建镜像和容器 5、启动镜像容器 6、验证nginx 三、Mysql 1、建立工作目录…...

使用Python Pandas实现两表对应列相加(即使表头不同)
目录 引言 Pandas库简介 实现对应列相加 步骤一:加载数据 步骤二:重命名列 步骤三:对应列相加 步骤四:保存结果 案例分析 结论 引言 在数据分析和处理的日常工作中,我们经常会遇到需要将来自不同数据源的数据…...

Linux 虚拟主机切换php版本及参数
我使用的Hostease的Linux虚拟主机产品,由于网站程序需要支持高版本的PHP,程序已经上传到主机,但是没有找到切换PHP以及查看PHP有哪些版本的位置,因此咨询了Hostease的技术支持,寻求帮助了解到可以实现在cPanel面板上找到此切换PHP版本的按钮&…...
Content-Type详解
...

GaussDB数据库SQL系列-复合查询
目录 一、前言 二、复合查询基础 三、实际应用示例 1、使用UNION合并查询结果 2、使用INTERSECT找出共同元素 3、使用EXCEPT排除特定结果 四、高级技巧 1、子查询实例 2、JOIN的应用 五、总结 一、前言 GaussDB是华为自主创新研发的分布式关系型数据库,具…...

【Unity】修改模型透明度
在 Unity 中修改模型透明度主要有两种方法:通过材质和通过着色器。以下是两种方法的步骤和解释: 方法 1:通过材质 在 Unity 编辑器中,选择你想要修改透明度的模型。在 Inspector 窗口中,找到模型的 Renderer 组件&am…...

第五篇:通信脉络:探索计算机外设与总线体系的精髓
通信脉络:探索计算机外设与总线体系的精髓 1 引言 在这个技术日新月异的时代,理解计算机系统的基本构成要素 —— 总线和外设 —— 对于每个从事技术工作的人来说都是至关重要的。这些组件不仅是计算机通信的基石,也直接影响着系统的性能、效…...

24.5.5(离散化+树状数组,线段树)
星期一: dp题单 背包 第四题 混可乐 cf传送门 思路:条件可演化为每种可乐值为 ai-n,选最少的可乐使总和为0(具体可看官方题解 到这会发现背包并不适合了,其实这是道bfs伪装的背包…...

C语言 | Leetcode C语言题解之第69题x的平方根
题目: 题解: int mySqrt(int x) {long int i 0;for(i0;;i){long int a i*i;long int b (i1)*(i1);if(a < x&&b > x){break;}}return i; }...

静态分配IP,解决本地连接不上Linux虚拟机的问题
在Window环境下,使用远程终端工具连接不了VMware搭建的Linux虚拟机(CentOS 7),并且在命令行ping不通该Linux虚拟机的IP地址。下面通过配置网关解决本地与Linux虚拟机连接问题: 1 查看虚拟机网关地址 在VMware虚拟机上…...
每日JAVA高级面试题
Java 高级面试问题及答案 以下是几个Java高级面试中可能会问到的问题,包括问题、答案以及一些探讨过程。 问题1: 请解释Java中的多线程以及线程池的使用场景和优势 答案: Java中的多线程允许程序执行多个任务,从而提高应用程序的响应速度和…...

修改JupyterNotebook文件存储位置
Jupyter Notebook 1、通过AnaConda安装Jupyter Notebok 2、在开始菜单里找到并打开Anaconda Prompt,输入如下命令,然后执行。 jupyter notebook --generate-config4、打开以下文件 找到 C:/Userzh/.../.jupyter 打开 jupyter_notebook_config.py 取消…...
python Flask路由系统如何影响应用性能的一些关键点
Flask的路由系统对应用性能的影响主要体现在路由匹配和分发请求的效率上。以下是关于Flask路由系统如何影响应用性能的一些关键点: 路由匹配方式:Flask支持精准匹配和模糊匹配两种方式。精准匹配是指URL中的路径和定义的路由规则完全匹配,而…...

nodejs的ws+vue3编写聊天室的demo
nodejs编写ws服务是非常简单高效的,nodejs有众多的实现ws的库,如ws,SocketIO等,nodejs的事件线程是单线程的,所以不要在事件线程内做阻塞性的操作,耗时的操作交给工作线程或者子进程操作。 我使用nodejsvue3实现了写了…...

《MySQL数据类型》
文章目录 一、理解数据本身就是一种约束1.tinyint类型和 tinyint unsigned类型2.其他的int类型 二、bit类型三、float类型1.signed版本注意2.unsigned版本 四、decimal类型float 和 decimal 总结五、char类型(固定长度)六、varchar类型(可变长…...

解决windows中的WSL Ubuntu子系统忘记root密码和用户密码问题
1、以管理员身份运行PowerShell 2、在powershell中执行wsl.exe --user root wsl.exe --user root如果出现了上面的报错,则需要运行步骤3、4,然后在执行步骤5改密码,如果没有出错,请直接跳到第5步改密码操作!ÿ…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
板凳-------Mysql cookbook学习 (十--2)
5.12 模式匹配中的大小写问题 mysql> use cookbook Database changed mysql> select a like A, a regexp A; ------------------------------ | a like A | a regexp A | ------------------------------ | 1 | 1 | --------------------------…...