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

java设计模式-生成器模式

文章目录

  • 生成器模式(Builder)
    • 1、目的和适用场景
    • 2、角色和职责
    • 3、实现步骤
    • 4、示例1
    • 5、示例2
    • 6、优点
    • 7、示例场景

生成器模式(Builder)

生成器模式(Builder Pattern)是一种创建型设计模式,它用于构造一个复杂对象的步骤分离。这样可以使用相同的构建过程创建不同的表示。生成器模式通常用于解决当一个对象需要多个部分来一步步构建时,直接实例化对象会导致构造方法过于复杂,参数列表过长的问题。使用生成器模式可以使对象的构建过程和表示分离,允许用户只通过指定复杂对象的类型和内容就可以构建它们,隐藏了对象的内部结构和构建过程。

1、目的和适用场景

生成器模式的主要目的是将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。这种模式特别适用于以下场景:

  • 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
  • 当构造过程必须允许被构造的对象有不同的表示时。

2、角色和职责

  1. 产品(Product):最终要创建的对象,通常包含多个组成部分。
  2. 生成器(Builder):定义创建产品对象所需的所有操作的接口或抽象类。
  3. 具体生成器(Concrete Builder):实现Builder接口的类,提供构建产品的具体实现。它负责创建产品对象的各个部分,并记录产品各部分的构造过程。
  4. 指导者(Director):负责安排已有模块的构造步骤,不涉及具体产品信息,只负责保证对象各部分完整创建或按某种顺序创建。
  5. 客户端(Client):使用生成器模式的地方,它将指导者和具体生成器关联起来,以创建复杂对象。

3、实现步骤

  1. 定义产品类:创建一个包含多个组成部件的复杂对象。
  2. 定义生成器接口:声明在所有类型生成器中通用的产品构造步骤。
  3. 实现具体生成器:为创建一个特定的产品变体提供实现。
  4. 定义指导者类:定义调用构建步骤的顺序来创建产品的方法。
  5. 客户端代码:创建一个生成器对象,将其传递给指导者,然后初始化构造过程。最后,从生成器对象中获取最终结果。

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)模式的使用场景主要集中在需要构建一个复杂对象时,特别是当这个对象的构造过程需要多个步骤,或者构造参数很多,而且许多参数具有默认值。具体的应用场景包括:

  1. 分离复杂对象的构造和表示
    当创建复杂对象的过程一致,但对象的内部表示可能变化时,生成器模式提供了非常灵活的解决方案。通过相同的构建过程可以创建不同的表示。
  2. 控制复杂对象的构造过程
    生成器模式将一个复杂对象的构造过程封装在其对应的生成器中,使得这个构造过程被局部化,且可以被重复使用。这样做还能使构造代码与表示代码分离,降低系统的耦合度。
  3. 参数过多的对象创建
    对于一个参数数量很多的对象,尤其是大多数参数都有默认值时,使用传统的构造函数会非常繁琐。生成器模式允许客户端仅通过必需的参数构造对象,并通过链式调用方式设置其他可选参数。
  4. 需要构建的对象应具有不同的变体,而不是重载大量构造函数
    当一个类需要大量的构造函数,参数组合较多时,使用生成器模式可以避免构造函数过多,使得构造过程更清晰。
  5. 创建复合对象
    复合对象是指那些包含其他对象的对象。对于这样的对象,使用生成器模式可以先创建其包含的对象,然后再按照一定的步骤和顺序构造复合对象。

7、示例场景

  • 文本转换器:将一个文档转换成多种格式,例如HTML、纯文本或者RTF格式。每种转换器都可以作为一个具体的生成器,而文档的读取过程则是统一的。
  • 用户界面构建器:在GUI应用程序中,可能需要创建复杂的用户界面。生成器模式可以逐步构建用户界面的各个部分,如菜单、工具栏、按钮等,最后组合成完整的用户界面。
  • SQL查询构造器:用于构建复杂的SQL查询,允许动态添加不同的条件、选择字段、设置排序规则等,最后生成完整的SQL语句。
    生成器模式通过将对象的构造过程从其表示中分离,使得相同的构建过程可以创建不同的表示,为复杂对象的创建提供了更高的灵活性和控制力。

相关文章:

java设计模式-生成器模式

文章目录 生成器模式&#xff08;Builder&#xff09;1、目的和适用场景2、角色和职责3、实现步骤4、示例15、示例26、优点7、示例场景 生成器模式&#xff08;Builder&#xff09; 生成器模式&#xff08;Builder Pattern&#xff09;是一种创建型设计模式&#xff0c;它用于…...

《前端面试题》- TypeScript - TypeScript的优/缺点

问题 简述TypeScript的优/缺点 答案 优点 增强了代码的可读性和可维护性包容性&#xff0c;js可以直接改成ts&#xff0c;ts编译报错也可以生成js文件&#xff0c;兼容第三方库&#xff0c;即使不是ts编写的社区活跃&#xff0c;完全支持es6 缺点 增加学习成本增加开发成…...

微服务---feign调用服务

目录 Feign简介 Feign的作用 Feign的使用步骤 引入依赖 具体业务逻辑 配置日志 在其它服务中使用接口 接着上一篇博客&#xff0c;我们讲过了nacos的基础使用&#xff0c;知道它是注册服务用的&#xff0c;接下来我们我们思考如果一个服务需要调用另一个服务的接口信息&…...

刷题笔记 - 滑动窗口

文章目录 滑动窗口最长无重复子串最小覆盖子串串联所有单词的子串长度最小的子数组滑动窗口最大值字符串的排列最小区间 滑动窗口 所有题目来自leetcode的回答&#xff1a;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库简介 实现对应列相加 步骤一&#xff1a;加载数据 步骤二&#xff1a;重命名列 步骤三&#xff1a;对应列相加 步骤四&#xff1a;保存结果 案例分析 结论 引言 在数据分析和处理的日常工作中&#xff0c;我们经常会遇到需要将来自不同数据源的数据…...

Linux 虚拟主机切换php版本及参数

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

Content-Type详解

...

GaussDB数据库SQL系列-复合查询

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

【Unity】修改模型透明度

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

第五篇:通信脉络:探索计算机外设与总线体系的精髓

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

24.5.5(离散化+树状数组,线段树)

星期一&#xff1a; dp题单 背包 第四题 混可乐 cf传送门 思路&#xff1a;条件可演化为每种可乐值为 ai-n&#xff0c;选最少的可乐使总和为0&#xff08;具体可看官方题解 到这会发现背包并不适合了&#xff0c;其实这是道bfs伪装的背包…...

C语言 | Leetcode C语言题解之第69题x的平方根

题目&#xff1a; 题解&#xff1a; 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环境下&#xff0c;使用远程终端工具连接不了VMware搭建的Linux虚拟机&#xff08;CentOS 7&#xff09;&#xff0c;并且在命令行ping不通该Linux虚拟机的IP地址。下面通过配置网关解决本地与Linux虚拟机连接问题&#xff1a; 1 查看虚拟机网关地址 在VMware虚拟机上…...

每日JAVA高级面试题

Java 高级面试问题及答案 以下是几个Java高级面试中可能会问到的问题&#xff0c;包括问题、答案以及一些探讨过程。 问题1: 请解释Java中的多线程以及线程池的使用场景和优势 答案&#xff1a; Java中的多线程允许程序执行多个任务&#xff0c;从而提高应用程序的响应速度和…...

修改JupyterNotebook文件存储位置

Jupyter Notebook 1、通过AnaConda安装Jupyter Notebok 2、在开始菜单里找到并打开Anaconda Prompt&#xff0c;输入如下命令&#xff0c;然后执行。 jupyter notebook --generate-config4、打开以下文件 找到 C:/Userzh/.../.jupyter 打开 jupyter_notebook_config.py 取消…...

python Flask路由系统如何影响应用性能的一些关键点

Flask的路由系统对应用性能的影响主要体现在路由匹配和分发请求的效率上。以下是关于Flask路由系统如何影响应用性能的一些关键点&#xff1a; 路由匹配方式&#xff1a;Flask支持精准匹配和模糊匹配两种方式。精准匹配是指URL中的路径和定义的路由规则完全匹配&#xff0c;而…...

nodejs的ws+vue3编写聊天室的demo

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

《MySQL数据类型》

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

解决windows中的WSL Ubuntu子系统忘记root密码和用户密码问题

1、以管理员身份运行PowerShell 2、在powershell中执行wsl.exe --user root wsl.exe --user root如果出现了上面的报错&#xff0c;则需要运行步骤3、4&#xff0c;然后在执行步骤5改密码&#xff0c;如果没有出错&#xff0c;请直接跳到第5步改密码操作&#xff01;&#xff…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Java毕业设计:WML信息查询与后端信息发布系统开发

JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发&#xff0c;实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构&#xff0c;服务器端使用Java Servlet处理请求&#xff0c;数据库采用MySQL存储信息&#xff0…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...