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步改密码操作!ÿ…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
