复杂对象的创建与组装 - 建造者模式(Builder Pattern)

建造者模式(Builder Pattern)

  • 建造者模式(Builder Pattern)
    • 建造者模式(Builder Pattern)概述
      • 建造者模式结构图
      • 代码
    • talk is cheap, show you my code
    • 总结

建造者模式(Builder Pattern)

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你分步骤构建复杂对象。该模式将一个复杂对象的构造与它的表示分离,使得同样的构建过程可以创建不同的表示。通过使用建造者模式,你可以避免大量参数化构造函数或多个重载构造函数带来的代码混乱,并且能够更容易地管理复杂的对象创建逻辑。

概念还是有一点抽象的
举个例子,作为一个平时打打游戏的同学,有时候会玩一种赛车游戏。赛车是可以自己定义与组装的。游戏中提供了各种各样的轮子,车体,引擎,悬架。。。 我们可以通过使用这些组件灵活地拼装出我们想要地自定义赛车。那么对这款游戏来说,我们自定义出来地车会有很多种类,那我们怎么实现这个效果呢? 使用建造者模式,具体细节请继续往下阅读。

建造者模式(Builder Pattern)概述

建造者模式结构图

在这里插入图片描述

代码

  1. 产品(Product): 最终被构建出来的复杂对象。它可以是一个具体的类,也可以是包含多个组件的对象。产品对象并不知道如何创建自己;相反,它依赖于建造者来完成其组装。
public class Product {private List<String> parts = new ArrayList<>();public void add(String part) {parts.add(part);}public void show() {System.out.println("Product contains the following parts:");for (String part : parts) {System.out.println(part);}}
}
  1. 抽象建造者(Builder):接口或抽象类,声明了用于构建各个组件的方法。具体建造者必须实现这些方法,以提供特定类型的对象构建逻辑。
public interface Builder {void buildPartA();void buildPartB();Product getResult();
}
  1. 具体建造者(ConcreteBuilder):实现了 Builder 接口的具体类。每个具体建造者都对应一种特定的产品类型,并负责一步一步地构建该产品的不同部分。
public class ConcreteBuilder implements Builder {private Product product = new Product();@Overridepublic void buildPartA() {product.add("PartA");}@Overridepublic void buildPartB() {product.add("PartB");}@Overridepublic Product getResult() {return product;}
}
  1. 指挥者(Director):指挥者类负责控制和协调建造者的操作顺序。它不直接创建产品实例,而是调用建造者提供的方法来逐步构建产品。这样做的好处是可以改变构建过程中的步骤顺序,而不影响客户端代码。
public class Director {private Builder builder;public Director(Builder builder) {this.builder = builder;}public void construct() {builder.buildPartA();builder.buildPartB();}
}

talk is cheap, show you my code

我们还是实现我们开头举的那个例子,实现一个可以自定义组装汽车的建造者模式代码。

class Car {private String body;private String engine;private String wheels;private String seats;// 私有构造函数,防止外部直接实例化private Car(CarBuilder builder) {this.body = builder.body;this.engine = builder.engine;this.wheels = builder.wheels;this.seats = builder.seats;}// 静态内部类,用于创建CarBuilder实例public static class CarBuilder {// 汽车部件protected String body;protected String engine;protected String wheels;protected String seats;// 设置车身的方法public CarBuilder setBody(String body) {this.body = body;return this; // 返回当前对象,支持链式调用}// 设置发动机的方法public CarBuilder setEngine(String engine) {this.engine = engine;return this;}// 设置车轮的方法public CarBuilder setWheels(String wheels) {this.wheels = wheels;return this;}// 设置座椅的方法public CarBuilder setSeats(String seats) {this.seats = seats;return this;}// 构建汽车的方法public Car build() {return new Car(this);}}// 展示汽车信息的方法@Overridepublic String toString() {return "Car{" +"body='" + body + '\'' +", engine='" + engine + '\'' +", wheels='" + wheels + '\'' +", seats='" + seats + '\'' +'}';}
}// 具体建造者类:豪华车建造者
class LuxuryCarBuilder extends Car.CarBuilder {@Overridepublic CarBuilder setBody(String body) {super.setBody("Luxury Body");return this;}@Overridepublic CarBuilder setEngine(String engine) {super.setEngine("V8 Engine");return this;}@Overridepublic CarBuilder setWheels(String wheels) {super.setWheels("Alloy Wheels");return this;}@Overridepublic CarBuilder setSeats(String seats) {super.setSeats("Leather Seats");return this;}
}// 具体建造者类:经济型车建造者
class EconomyCarBuilder extends Car.CarBuilder {@Overridepublic CarBuilder setBody(String body) {super.setBody("Economy Body");return this;}@Overridepublic CarBuilder setEngine(String engine) {super.setEngine("4 Cylinder Engine");return this;}@Overridepublic CarBuilder setWheels(String wheels) {super.setWheels("Steel Wheels");return this;}@Overridepublic CarBuilder setSeats(String seats) {super.setSeats("Fabric Seats");return this;}
}// 指挥者类:汽车工厂
class CarDirector {private Car.CarBuilder builder;public CarDirector(Car.CarBuilder builder) {this.builder = builder;}// 指挥构建汽车的方法public Car constructCar() {return builder.setBody("Default Body") // 可以被具体建造者覆盖.setEngine("Default Engine") // 可以被具体建造者覆盖.setWheels("Default Wheels") // 可以被具体建造者覆盖.setSeats("Default Seats") // 可以被具体建造者覆盖.build();}
}// 客户端代码
public class Main {public static void main(String[] args) {// 创建豪华车CarDirector luxuryDirector = new CarDirector(new LuxuryCarBuilder());Car luxuryCar = luxuryDirector.constructCar();System.out.println(luxuryCar);// 创建经济型车CarDirector economyDirector = new CarDirector(new EconomyCarBuilder());Car economyCar = economyDirector.constructCar();System.out.println(economyCar);}
}

在这个例子中,Car类有一个私有构造函数,只能通过CarBuilder内部类来创建实例。CarBuilder是一个抽象建造者,提供了设置汽车各个部件的方法,并返回当前对象以支持链式调用。LuxuryCarBuilder和EconomyCarBuilder是具体建造者,它们覆盖了CarBuilder中的方法以提供不同类型的汽车部件。CarDirector是指挥者,它使用CarBuilder接口来构建汽车,但允许具体建造者提供特定的实现。

客户端代码通过创建CarDirector实例并传递具体的CarBuilder来构建不同类型的汽车。这样,客户端代码与具体的汽车构建过程解耦,只需要知道如何创建指挥者和选择具体的建造者即可。

总结

建造者模式优点:

  • 减少大量的构造函数参数:当一个类有很多可选参数时,可以通过建造者模式来避免长而复杂的构造函数签名。
  • 提高代码可读性:通过链式调用(Fluent Interface),可以使对象创建更加直观和易懂。
  • 易于扩展:如果需要添加新的组件或改变构建逻辑,只需新增具体建造者类,而不需要修改现有代码。
  • 符合单一职责原则:建造者模式让每个类只专注于一件事,即构建某个特定类型的产品。

建造者模式的应用场景

  • 复杂对象创建
  • 多步骤过程
  • 变种对象

建造者模式是一个非常有用的设计模式,特别是在需要处理具有多个可选参数或复杂创建逻辑的对象时。它帮助开发者更好地组织代码,提高系统的灵活性和可维护性。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux-mac地址

mac地址 由6位16进制数组成。最高字节的最低位&#xff0c;0表示单播地址&#xff0c;1表示多播地址。最高字节的第二位&#xff0c;0表示全局地址&#xff0c;1表示本地地址。 单播地址&#xff1a;单播MAC地址用于一对一的通信模式&#xff0c;即从单一的源端发送到单一的目…

SAP学习笔记 - 豆知识14 - Msg 番号 M7562 - 取引Type WL 对应的番号範囲中不存在2025年度 OMBT

这种类似的以前也写过&#xff0c;原因就是自动採番的番号没弄。 比如跨年了&#xff0c;那该新年度的番号范围没弄啊&#xff0c;就会出这种错误。 把番号范围给加一下就可以了。 1&#xff0c;现象 比如点 VL02N 出荷传票变更 画面&#xff0c;点 出库确认 就会出如下错误…

一文理清JS中获取盒子宽高各方法的差异

前言 这段时间在研究一个反爬产品&#xff0c;环境检测用到了很多个盒子宽高取值方法&#xff0c;如window.outerWidth、window.screen.availWidth&#xff0c;各个方法取值结果不大相同&#xff0c;在此记录下遇到的方法。 各宽方法区别 这里就讲解下各宽度方法的区别&…

sqoop将MySQL数据导入hive

使用脚本加载数据 MySQL有一张表 hive创建一张相同的表 编写脚本同步数据 [rootmaster sqoop]# vim stu.sh#!/bin/bash SQOOP/usr/local/soft/sqoop-1.4.6/bin/sqoop $SQOOP import --connect jdbc:mysql://192.168.67.100:3306/sqoop \--username root \--password 123456 \-…

Docker Compose编排

什么是 Docker Compose? Docker Compose 是 Docker 官方推出的开源项目&#xff0c;用于快速编排和管理多个 Docker 容器的应用程序。它允许用户通过一个 YAML 格式的配置文件 docker-compose.yml 来定义和运行多个相关联的应用容器&#xff0c;从而实现对容器的统一管理和编…

[羊城杯 2024]hiden

一顿解压之后发现有两个文件&#xff1a; 尝试了Rot47解密&#xff0c;得到一个看起来挺像一回事的解码结果&#xff1a; 再将得到的解码结果试试Rot13解密&#xff0c;成功得到正确的解码结果&#xff1a; import wave with open(flag.txt, rb) as f:txt_data f.read()file_l…

LeetCode - 初级算法 数组(只出现一次的数字)

只出现一次的数字 这篇文章讨论如何找到一个数组中只出现一次的数字,确保算法的时间复杂度为线性,且只使用常量额外空间。 免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 描述 给定一个非空整数数组 nums,除了某个元素只出现一次以外,其余每个元素均出现两…

【谷歌开发者月刊】十二月精彩资讯回顾,探索科技新可能

我们在今年的尾声中回顾本月精彩&#xff0c;开发者们借助创新技术为用户打造温暖的应用体验&#xff0c;展现技术与实用的结合。欢迎您查阅本期月刊&#xff0c;掌握最新动态。 本月看点 精彩看点多多&#xff0c;请上下滑动阅览 01DevFest 北京站和上海站圆满举办&#xff0c…

LinuxC高级day4

作业: 1.思维导图 2.终端输入一个C源文件名(.c结尾)判断文件是否有内容&#xff0c;如果没有内容删除文件&#xff0c;如果有内容编译并执行改文件。 3.终端输入两个文件名&#xff0c;判断哪个文件的时间戳更新

数据中台与数据治理服务方案[50页PPT]

本文概述了数据中台与数据治理服务方案的核心要点。数据中台作为政务服务数据化的核心&#xff0c;通过整合各部门业务系统数据&#xff0c;进行建模与加工&#xff0c;以新数据驱动政府管理效率提升与政务服务能力增强。数据治理则聚焦于解决整体架构问题&#xff0c;确保数据…

MAC环境安装(卸载)软件

MAC环境安装&#xff08;卸载&#xff09;软件 jdknode安装node&#xff0c;并实现不同版本的切换背景 卸载node从node官网下载pkg安装的node卸载用 homebrew 安装的node如果你感觉删的不够干净&#xff0c;可以再细分删除验证删除结果 jdk 1.下载jdk 先去官网下载自己需要的版…

时间序列预测算法---LSTM

文章目录 一、前言1.1、深度学习时间序列一般是几维数据&#xff1f;每个维度的名字是什么&#xff1f;通常代表什么含义&#xff1f;1.2、为什么机器学习/深度学习算法无法处理时间序列数据?1.3、RNN(循环神经网络)处理时间序列数据的思路&#xff1f;1.4、RNN存在哪些问题?…

LinuxC高级day2

1.在家目录下创建目录文件&#xff0c;dir a.dir下创建dir1和dir2 b.把当前目录下的所有文件拷贝到dir1中&#xff0c; c.把当前目录下的所有脚本文件拷贝到dir2中 d.把dir2打包并压缩为dir2.tar.xz e.再把dir2.tar.xz移动到dir1中 f.解压dir1中的压缩包 g.使用tree工具&#x…

14. 日常算法

1. 面试题 02.04. 分割链表 题目来源 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你不需要 保留 每个分区中各节点的初始相对位置。 class Solution { public:ListNo…

ubuntu 如何使用vrf

在Ubuntu或其他Linux系统中&#xff0c;您使用ip命令和sysctl命令配置的网络和内核参数通常是临时的&#xff0c;这意味着在系统重启后这些配置会丢失。为了将这些配置持久化&#xff0c;您需要采取一些额外的步骤。 对于ip命令配置的网络接口和路由&#xff0c;您可以将这些配…

SpringMVC进阶(自定义拦截器以及异常处理)

文章目录 1.自定义拦截器 1.基本介绍 1.说明2.自定义拦截器的三个方法3.流程图 2.快速入门 1.Myinterceptor01.java2.FurnHandler.java3.springDispatcherServlet-servlet.xml配置拦截器4.单元测试 3.拦截特定路径 1.拦截指定路径2.通配符配置路径 4.细节说明5.多个拦截器 1.执…

Mac电脑python多版本环境安装与切换

我当前是python3.9.6环境&#xff0c;需要使用3.9.8环境&#xff0c;通过brew安装3.9.8版本&#xff0c;然后通过pyenv切换环境 步骤 1: 安装 pyenv brew install pyenv brew install pyenv-virtualenv 步骤 2: 安装 Python 3.9.8&#xff08;使用 pyenv 安装指定版本的 Pyth…

【蓝桥杯——物联网设计与开发】拓展模块4 - 脉冲模块

目录 一、脉冲模块 &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;采集原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#xff08;4&#xff09;实验现象 二、脉冲模块接口函数封装 三、踩坑日记 &a…

基于服务器部署的综合视频安防系统的智慧快消开源了。

智慧快消视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。国产化人工智能“…

12.31【Linux】shell脚本【运行方式,修改环境变量,数组】思维导图 内附练习

1.思维导图 2练习&#xff1a; 1.尝试将下列指令放到脚本中运行 在家目录下创建目录文件dir1&#xff0c;把/etc/passwd拷贝到dir1中&#xff0c;把/etc/group拷贝到dir1中并重命名为grp.txt&#xff0c;使用tree指令&#xff0c;显示dir1目录的文件树&#xff0c;把dir1&am…