Java 设计模式——建造者模式

目录

  • 1.概述
  • 2.结构
  • 3.实例
    • 3.1.产品类
    • 3.2.抽象建造者类
    • 3.3.具体建造者类
    • 3.4.指挥者类
    • 3.5.测试
  • 4.优缺点
  • 5.使用场景
  • 6.模式扩展
  • 7.创建者模式对比

1.概述

建造者模式 (Builder Pattern) 是一种创建型设计模式,用于创建复杂对象。它将对象的构建过程分离成独立的部分,同时允许按照不同的方式构建对象。通常情况下,当一个对象的构建过程有多个步骤,且这些步骤可以按照不同的顺序来构建时,建造者模式就非常有用。通过将构建逻辑封装到具体的建造者类中,客户端可以使用相同的构建过程来创建不同类型的对象。

2.结构

建造者模式包含如下角色:

  • 抽象建造者类 (Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的部件对象的创建。
  • 具体建造者类 (ConcreteBuilder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
  • 产品类 (Product):要创建的复杂对象。
  • 指挥者类 (Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。类图如下:
    在这里插入图片描述

3.实例

【例】创建共享单车:生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。这里 Bike 是产品,包含车架,车座等组件;Builder 是抽象建造者,MobikeBuilder 和 OfoBuilder 是具体的建造者;Director 是指挥者。类图如下:
在这里插入图片描述
具体代码如下:

3.1.产品类

Bike.java

public class Bike {private String frame;//车架private String seat;//车座public String getFrame() {return frame;}public void setFrame(String frame) {this.frame = frame;}public String getSeat() {return seat;}public void setSeat(String seat) {this.seat = seat;}
}

3.2.抽象建造者类

Builder.java

public abstract class Builder {//声明Bike类型的变量,并进行赋值protected Bike bike = new Bike();public abstract void buildFrame();public abstract void buildSeat();//构建自行车的方法public abstract Bike createBike();
}

3.3.具体建造者类

MobileBuilder.java

//具体的构建者,用来构建摩拜单车对象
public class MobileBuilder extends Builder{public void buildFrame() {bike.setFrame("碳纤维车架");}public void buildSeat() {bike.setSeat("真皮车座");}public Bike createBike() {return bike;}
}

OfoBuilder.java

public class OfoBuilder extends Builder{public void buildFrame() {bike.setFrame("铝合金车架");}public void buildSeat() {bike.setSeat("橡胶车座");}public Bike createBike() {return bike;}
}

3.4.指挥者类

Director.java

public class Director {//声明 builder 类型的变量private Builder builder;public Director(Builder builder) {this.builder = builder;}//组装自行车的功能public Bike construct() {builder.buildFrame();builder.buildSeat();return builder.createBike();}
}

3.5.测试

Client.java

public class Client {public static void main(String[] args) {//创建指挥者对象Director director = new Director(new MobileBuilder());//让指挥者只会组装自行车Bike bike = director.construct();System.out.println(bike.getFrame());System.out.println(bike.getSeat());}
}

注意:上面示例是 Builder 模式的常规用法,指挥者类 Director 在建造者模式中具有很重要的作用,它用于指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类,但是有些情况下需要简化系统结构,可以把指挥者类和抽象建造者进行结合。

// 抽象 builder 类
public abstract class Builder {protected Bike mBike = new Bike();public abstract void buildFrame();public abstract void buildSeat();public abstract Bike createBike();public Bike construct() {this.buildFrame();this.BuildSeat();return this.createBike();}
}

4.优缺点

(1)建造者模式具有以下几个优点:

  • 分离构建过程和表示:建造者模式可以将一个复杂对象的构建过程与它的表示分离,使得相同的构建过程可以创建不同的表示。这样可以使代码结构更清晰,易于阅读和维护。
  • 隐藏产品内部细节:建造者模式将对象的构建过程封装在具体的建造者类中,使得客户端可以不需要知道产品的内部实现细节,只需要关注如何组装和使用产品。
  • 提供更好的控制:由于建造者模式将构建过程分步进行,可以通过指定不同的具体建造者,实现不同的构建过程。这样就可以更灵活地控制构建过程,根据需要定制复杂对象的创建方式。

(2)建造者模式的一些缺点包括:

  • 增加了代码量:引入建造者模式会增加额外的代码量,因为需要定义抽象建造者和具体建造者类,以及指挥者类等。对于简单的对象构建过程,可能会显得繁琐。
  • 对客户端的要求高:客户端需要显式地创建指挥者对象,并指定具体的建造者,且需要了解建造者类的接口和使用方法。这对于不熟悉建造者模式的开发人员来说可能会增加学习成本。

综上所述,建造者模式在创建复杂对象时具有很多优点,但也需要在实际应用中权衡其优缺点来决定是否使用。

5.使用场景

(1)建造者模式适用于以下几种场景:

  • 当对象的构建过程比较复杂,需要有多个步骤或者按照不同的顺序构建时,可以使用建造者模式。例如,创建一个包含多个部分的电子产品,每个部分的构建方式可能不同,而且可以按照不同的顺序组装。
  • 当需要创建的对象有多个不同的表示或配置时,可以使用建造者模式。使用不同的具体建造者可以创建不同的对象表示,而且可以在运行时动态地选择具体建造者。
  • 当想要隔离产品的构造和表示细节,使得构造过程和最终的产品解耦时,可以使用建造者模式。客户端只需要关注构建过程和产品的使用,而不需要关注产品的内部实现细节。
  • 当需要创建一系列相似但稍有差异的对象时,可以使用建造者模式。通过复用相同的构建逻辑和变化的部分,可以高效地创建多个对象。
  • 当需要在一个对象的构建过程中能够灵活地修改构建方式或者增加更多的构建步骤时,可以使用建造者模式。具体建造者的实现可以根据需求进行扩展和修改,而不会影响到客户端代码。

(2)需要注意的是,如果对象的构建过程相对简单,没有多个步骤或者差异很小,或者只有少数几个属性需要设置,那么使用建造者模式可能会显得过于繁琐,可以考虑使用其他创建型模式或者简化构建过程。

6.模式扩展

建造者模式除了上面的用途外,在开发中还有一个常用的使用方式,就是当一个类构造器需要传入很多参数时,如果创建这个类的实例,代码可读性会非常差,而且很容易引入错误,此时就可以利用建造者模式进行重构
(1)重构前代码如下:
Phone.java

public class Phone {private String cpu;private String screen;private String memory;private String mainboard;public Phone(String cpu, String screen, String memory, String mainboard) {this.cpu = cpu;this.screen = screen;this.memory = memory;this.mainboard = mainboard;}@Overridepublic String toString() {return "Phone{" +"cpu='" + cpu + '\'' +", screen='" + screen + '\'' +", memory='" + memory + '\'' +", mainboard='" + mainboard + '\'' +'}';}
}

Client.java

public class Client {public static void main(String[] args) {//构建Phone对象Phone phone = new Phone("麒麟","三星屏幕","金士顿","华硕主板");System.out.println(phone);}
}

上面在客户端代码中构建Phone对象,传递了四个参数,如果参数更多,那么代码的可读性会变差,以及使用的成本会变高。

(2)重构后代码如下:
Phone.java

public class Phone {private String cpu;private String screen;private String memory;private String mainboard;private Phone(Builder builder) {cpu = builder.cpu;screen = builder.screen;memory = builder.memory;mainboard = builder.mainboard;}public static final class Builder{private String cpu;private String screen;private String memory;private String mainboard;public Builder(){}public Builder cpu(String val){cpu = val;return this;}public Builder screen(String val){screen = val;return this;}public Builder memory(String val){memory = val;return this;}public Builder mainboard(String val){mainboard = val;return this;}public Phone build(){return new Phone(this);}}@Overridepublic String toString() {return "Phone{" +"cpu='" + cpu + '\'' +", screen='" + screen + '\'' +", memory='" + memory + '\'' +", mainboard='" + mainboard + '\'' +'}';}
}

Client.java

public class Client {public static void main(String[] args) {//构建Phone对象Phone phone = new Phone.Builder().cpu("麒麟").memory("金士顿").screen("三星屏幕").mainboard("华硕").build();System.out.println(phone);}
}

重构后的代码在使用起来更方便,某种程度上也可以提高开发效率。从软件设计上,对程序员的要求比较高。

7.创建者模式对比

(1)工厂方法模式 VS 建造者模式
工厂方法模式注重的是整体对象的创建方式;而建造者模式注重的是部件构建的过程,意在通过一步一步地精确构造创建出一个复杂的对象。

(2)抽象工厂模式 VS 建造者模式

  • 抽象工厂模式实现对产品家族的创建,一个产品家族是这样的一系列产品:具有不同分类维度的产品组合,采用抽象工厂模式则是不需要关心构建过程,只关心什么产品由什么工厂生产即可。
  • 建造者模式则是要求按照指定的蓝图建造产品,它的主要目的是通过组装零配件而产生一个新产品。 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。

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

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

相关文章

前端 | iframe框架标签应用

文章目录 📚嵌入方式📚图表加载显示📚100%嵌入及滑动条问题📚加载动画保留 前情提要: 计划用iframe把画好的home1.html(echarts各种图表组成的html数据大屏)嵌入整合到index.html(搭…

快速筛出EXCEL行中的重复项

比如A列是一些恶意IP需要导入防火墙,但包括一些重复项,为不产生错误,需要把重复项筛出来: 1、给A列排序,让重复项的内容排在相邻的行 2、在B列中写一个条件函数:IF(A1A2,1,0),然后下拉至行尾完成…

java设计模式 开闭原则

开闭原则(Open-Closed Principle,OCP)是面向对象设计中的一个重要原则,它指导着我们如何设计和组织代码,以便使系统在扩展性和可维护性方面更加优秀。 开闭原则的定义是:软件实体(类、模块、函数…

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO

ESP32-Web-Server 实战编程-通过网页控制设备的 GPIO 概述 前述博客讲解了 Web 编程的基本知识,包括 HTML、CSS、JavaScript 三个部分,从这节开始,我们进入实战部分,在实际项目中进一步学习 ESP32-Web 编程。 GPIO &#xff08…

WebGL笔记:图形旋转的原理和实现

旋转 1 )旋转的概念 三维物体的旋转要比位移复杂一点,三维物体的旋转需要满足以下条件: 旋转轴旋转方向旋转角度 场景举例 模型站在旋转轴的起点进行旋转模型要往左转还是往右转,就是旋转的方向模型旋转的大小就是旋转角度 2 &…

人工智能_AI服务器安装清华开源_CHATGLM大语言模型_GLM-6B安装部署_人工智能工作笔记0092

看到的这个开源的大模型,很牛,~关键让我们自己也可以部署体验一把了,虽然不知道具体内部怎么构造的但是,也可以自己使用也挺好. 可以部署在自己的机器上也可以部署在云服务器上. 安装以后,是可以使用python代码进行提问,然后返回结果的,这样就可以实现我们自己的chat应用了, …

仿美团外卖源码/在线外卖平台源码PHP/支持多商户+多样化配送费+本土外卖+支持第三方配送

源码简介: 进云仿美团外卖源码,作为外卖平台源码,它不仅支持多商户、多样化配送费、本土外卖,还支持第三方配送。 进云仿美团外卖源码是一个进云源生插件,支持多商户多样化配送费模式本土外卖平台支持第三方配送&…

excel表格在线编辑(开源版)

文章目录 前言一、Luckysheetvue3vite 例子如有启发,可点赞收藏哟~ 前言 本文记录好用的开源在线表格 具体如图显示 另外记录下更名后的univer~,如下图(有兴趣可自行详细了解) univer 在线思维导图 一、Luckysheet 参考git…

蓝桥杯day02——移动机器人

1.题目 有一些机器人分布在一条无限长的数轴上,他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时,它们以每秒钟一单位的速度开始移动。 给你一个字符串 s ,每个字符按顺序分别表示每个机器人移动的方向。L 表…

基于Vue+SpringBoot的个人健康管理系统

项目编号: S 040 ,文末获取源码。 \color{red}{项目编号:S040,文末获取源码。} 项目编号:S040,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 健康档案模块2.2 体检档案模块2.3 健…

C语言第三十六弹--实现转移表的多种方法

使用C语言通过多种方法实现转移表 方法一、普通法 思路:如图实现多种操作,首先创建菜单,需要运行一次再判断条件,所以通过do{}while(); 循环来实现多次。有多种选择,使用switch case选择语句,再在对应case…

内网渗透(哈希传递)

概念 早期SMB协议明文在网络上传输数据,后来诞生了LM验证机制,LM机制由于过于简单,微软提出了WindowsNT挑战/响应机制,这就是NTLM。 哈希传递前提 同密码(攻击主机与实现主机两台要密码一致)。 NTLM协议 加密ntlm哈希 转换成…

uniapp中uni.navigateBack返回后刷新页面数据

文章目录 一、前言1.1、[uni.navigateBack](https://uniapp.dcloud.net.cn/api/router.html#navigateback) 二、方法2.1、父页面设置钩子函数onBackPress2.2、uni.$emit和uni.$on监听通知数据变更2.2.1、子页面2.2.2、父页面 2.3、onShow钩子函数处理数据2.3.1、子页面2.3.2、父…

使用Python实现SVM来解决二分类问题

下面是一个使用Python实现SVM来解决二分类问题的例子: # 导入所需的库 from sklearn.datasets import make_blobs from sklearn.model_selection import train_test_split from sklearn.svm import SVC import matplotlib.pyplot as plt# 生成一个二分类数据集 X, …

MES系统的功能清单

MES系统的功能清单 一、生产计划管理 1. 订单和生产计划制定:根据客户需求和市场状况,制定生产计划和订单,确保生产资源的合理分配和生产进度的有效管理。 2. 生产排程:根据生产计划和订单,结合设备、人员、物料等资…

iOS 通用链接的配置(Universal Links)

一、打开Associated Domains 1.首先登录 苹果开发者网站 2.Certificates, Identifiers & Profiles 下的Identifiers 找到要配追的Identifiers 点进去 3.打开Associated Domains然后保存 二、更新Profile文件 如果我们使用自动的,可以忽略这一步,…

与珎同行录-开篇-231129

与珎同行录-开篇 珎就是对陪伴并帮助我写代码的AI的昵称 能不能读懂这个绕口令问题呢? 连续的椎体的相邻椎体质心的相邻质心的质心作为当前质心所在的椎体的质心, 该质心的方向代表该椎体的上下方向 如何代码实现呢? 还是没看懂…好吧最终的算法是:

使用Pytorch从零开始构建扩散模型-DDPM

知识回顾: [1] 生成式建模概述 [2] Transformer I,Transformer II [3] 变分自编码器 [4] 生成对抗网络,高级生成对抗网络 I,高级生成对抗网络 II [5] 自回归模型 [6] 归一化流模型 [7] 基于能量的模型 [8] 扩散模型 I, 扩散模型 II 引言 去噪…

什么是量子优势?

量子优势是量子计算领域正在积极努力的里程碑,量子计算机可以解决最强大的非量子或经典计算机无法解决的问题。 量子是指原子和分子的尺度,在这个尺度上,我们所经历的物理定律被打破,并且应用了一组不同的、违反直觉的定律。量子…

西南科技大学数字电子技术实验二(SSI逻辑器件设计组合逻辑电路及FPGA实现 )预习报告

一、计算/设计过程 说明:本实验是验证性实验,计算预测验证结果。是设计性实验一定要从系统指标计算出元件参数过程,越详细越好。用公式输入法完成相关公式内容,不得贴手写图片。(注意:从抽象公式直接得出结果,不得分,页数可根据内容调整) 1、1位半加器 真值表: 逻…