Java设计模式:建造者模式之经典与流式的三种实现(四)

本文将深入探讨Java中建造者模式的两种实现方式:经典建造者与流式建造者。建造者模式是一种创建型设计模式,它允许你构建复杂对象的步骤分解,使得对象的创建过程更加清晰和灵活。我们将通过示例代码详细解释这两种实现方式,并分析它们各自的特点和使用场景。

[参见]:

Java设计模式:核心概述(一)

Java设计模式:单例模式之六种实现方式详解(二)

Java设计模式:工厂模式之简单工厂、工厂方法、抽象工厂(三)

目录

    • 一、前言
    • 二、建造者模式的使用场景
    • 三、建造者模式的三种实现方式
      • 3.1 经典建造者模式
      • 3.2 流式建造者模式
      • 3.3 使用Lombok库实现流式建造者模式
    • 四、建造者模式的注意事项
    • 五、结语

一、前言

开发中,我们经常需要创建具有多个属性或配置选项的复杂对象。直接通过构造函数或大量的setter方法来设置这些属性可能会导致代码的可读性和维护性下降。建造者模式通过提供一个建造者类来封装复杂对象的创建过程,使得客户端代码可以更加简洁和清晰地构建对象。

二、建造者模式的使用场景

  1. 当对象有多个构造函数参数时:如果一个类的构造函数需要多个参数,而这些参数中有些是可选的,那么使用建造者模式可以更加清晰地表达对象的创建过程,避免构造函数的参数列表过长和混乱。

  2. 当对象的构建过程需要多个步骤时:如果对象的创建过程涉及多个步骤,并且这些步骤的顺序很重要,那么建造者模式可以确保这些步骤按照正确的顺序执行,并提供一种灵活的方式来调整这些步骤。

  3. 当需要创建不同配置的对象变体时:如果需要根据不同的配置选项创建对象的多个变体,那么建造者模式可以提供一种清晰的方式来表示这些配置选项,并根据需要构建不同的对象变体。

  4. 当对象的构建过程需要复杂的逻辑时:如果对象的构建过程涉及复杂的逻辑,如验证参数的有效性、计算属性的默认值等,那么建造者模式可以将这些逻辑封装在建造者类中,使客户端代码更加简洁和清晰。

在这里插入图片描述


三、建造者模式的三种实现方式

Java中,实现建造者设计模式通常有两种主要方式:经典的建造者模式(也称为分步构建器)和流式建造者模式(也称为流畅接口构建器或链式调用构建器)。第三种借用lomback自动生成流式建造者模式,所以实际是两种方式。

3.1 经典建造者模式

经典建造者模式通常包括一个产品类、一个抽象建造者接口、一个具体建造者类和一个指挥者类(可选)。产品类包含需要设置的属性和访问器方法。抽象建造者接口定义了构建产品所需的各个步骤。具体建造者类实现了抽象建造者接口,并提供了设置产品属性和获取构建好的产品对象的方法。

然而,在实际应用中,我们往往可以省略指挥者类,直接在客户端代码中操作具体建造者来构建产品对象。这种方式简化了经典建造者模式的结构,但仍然保留了其逐步构建对象的优点。

代码:

// 产品类  
public class Product {  private String partA;  private String partB;  private String partC;  // 构造方法可以是私有的,因为建造者模式可以控制对象的构建过程  private Product() {}  public String getPartA() {  return partA;  }  public void setPartA(String partA) {  this.partA = partA;  }  // 省略其他getter和setter方法...  // 静态内部类作为具体建造者  public static class Builder {  private Product product;  public Builder() {  product = new Product();  }  public Builder setPartA(String partA) {  product.partA = partA;  return this; // 返回当前Builder实例,以便链式调用  }  public Builder setPartB(String partB) {  product.partB = partB;  return this;  }  public Builder setPartC(String partC) {  product.partC = partC;  return this;  }  // 创建并返回产品对象  public Product build() {  return product;  }  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  Product product = new Product.Builder()  .setPartA("This is part A")  .setPartB("This is part B")  .setPartC("This is part C")  .build();  System.out.println(product.getPartA());  // 省略访问其他部分...  }  
}

Product 类有一个静态内部类 Builder,它负责构建 Product 对象。客户端代码通过调用 Builder 的方法来设置产品的各个部分,并最终调用 build() 方法来获取构建好的产品对象。

3.2 流式建造者模式

流式建造者模式是经典建造者模式的一种变体,它更加强调链式调用的流畅性。在流式建造者模式中,产品类通常包含一个静态内部类作为流式建造者。这个内部类提供了设置产品属性的方法,并返回自身的实例以支持链式调用。最后,通过一个build()方法返回构建好的产品对象。

流式建造者模式省略了经典建造者模式中的抽象建造者接口和指挥者类,使得代码更加简洁和直观。同时,通过链式调用的方式设置产品属性,可以提高代码的可读性和编写的灵活性。

代码:

// 产品类  
public class Product {  private String partA;  private String partB;  private String partC;  // 私有构造方法,防止直接实例化  private Product() {}  // 省略getter方法...  // 静态内部类作为流式建造者  public static class Builder {  private String partA;  private String partB;  private String partC;  public Builder withPartA(String partA) {  this.partA = partA;  return this;  }  public Builder withPartB(String partB) {  this.partB = partB;  return this;  }  public Builder withPartC(String partC) {  this.partC = partC;  return this;  }  // 创建产品对象  public Product build() {  Product product = new Product();  product.partA = this.partA;  product.partB = this.partB;  product.partC = this.partC;  return product;  }  }  
}  // 客户端代码  
public class Client {  public static void main(String[] args) {  Product product = new Product.Builder()  .withPartA("This is part A")  .withPartB("This is part B")  .withPartC("This is part C")  .build();  // 省略访问产品属性的代码...  }  
}

Builder 类的每个设置方法都返回 Builder 类型的实例(即 this),从而允许链式调用。这种方式使得客户端代码更加简洁和易读。注意,在这个实现中,Product 类的构造方法是私有的,以防止外部直接实例化。所有的属性设置都是通过 Builder 进行的。

3.3 使用Lombok库实现流式建造者模式

Lombok 是一个 Java 库,它可以通过注解来简化 Java 代码,例如自动生成 getter、setter、equals、hashCode 和 toString 方法等。其中,@Builder 注解就是用来实现建造者模式的一个简化工具。

使用 Lombok 的 @Builder 注解,你不需要手动编写建造者模式的代码。只需要在类定义上添加 @Builder 注解,Lombok 就会在编译时自动生成相应的建造者类。

下面是一个使用 Lombok @Builder 注解来实现建造者模式的代码:

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;@Getter
@Setter
@Builder
public class Person {private String name;private int age;private String address;// 使用 Lombok @Builder 注解后,无需再手动编写建造者模式的代码// Lombok 会在编译时自动生成一个名为 Person.PersonBuilder 的内部类// 下面是如何使用生成的建造者类来构建 Person 对象的示例public static void main(String[] args) {Person person = Person.builder().name("John Doe").age(30).address("123 Main St").build();System.out.println(person);}
}

在这个例子中,我们定义了一个 Person 类,并使用了 @Getter@Setter@Builder 注解。@Getter@Setter 注解分别用于生成 getter 和 setter 方法,而 @Builder 注解则用于生成建造者模式的代码。

main 方法中,我们使用 Person.builder() 方法来获取一个 PersonBuilder 实例,然后通过链式调用设置 nameageaddress 属性,最后调用 build() 方法来构建 Person 对象。

以上使用 Lombok 的 @Builder 注解所生成的代码在编译时会创建一个内部类,这个内部类通常命名为 类名Builder,在这个例子中是 PersonBuilder。这个内部类会包含对应类中所有字段的设置方法以及一个 build() 方法来创建目标对象。

生成的代码大致相当于手动实现的流式建造者模式,因为它允许通过链式调用的方式来设置对象的属性。不过,由于 Lombok 自动处理了这些细节,用户无需手动编写这些代码。

假设没有 Lombok,并且我们要手动实现上述 Person 类的建造者模式,代码可能看起来像这样:

public class Person {private String name;private int age;private String address;private Person(Builder builder) {this.name = builder.name;this.age = builder.age;this.address = builder.address;}public static class Builder {private String name;private int age;private String address;public Builder() {}public Builder name(String name) {this.name = name;return this;}public Builder age(int age) {this.age = age;return this;}public Builder address(String address) {this.address = address;return this;}public Person build() {return new Person(this);}}// getters, setters, toString, etc.
}

使用 Lombok,上面的所有建造者逻辑都会在编译时自动生成,你不需要手动编写这些代码。Lombok 会创建一个与上述手动实现的 Builder 类类似的内部类,并提供同样的链式调用功能。

在这里插入图片描述


四、建造者模式的注意事项

  1. 避免滥用建造者模式:虽然建造者模式可以提供一种清晰和灵活的方式来构建复杂对象,但过度使用它可能会导致代码变得复杂和难以维护。因此,在决定使用建造者模式之前,应该仔细评估对象的复杂性和构建过程的需求。

  2. 考虑建造者的可重用性:如果对象的构建过程涉及一些可重用的步骤或组件,那么可以设计可重用的建造者类来减少代码重复和提高可维护性。例如,可以创建一些通用的建造者类来处理常见的构建步骤,并在需要时进行扩展或定制。

  3. 注意与工厂模式的区别:建造者模式与工厂模式都是创建型设计模式,但它们的职责和用途有所不同。工厂模式主要负责对象的创建和实例化,而建造者模式则关注于对象的构建过程和属性的设置。在实际应用中,可以根据需要选择使用哪种模式或结合使用它们。

五、结语

  • 建造者模式是一种强大且灵活的设计模式,适用于构建具有多个属性和复杂构建过程的对象。
  • 通过合理使用建造者模式,可以提高代码的可读性、可维护性和可扩展性。
  • 然而,在使用建造者模式时,也需要注意避免滥用、考虑线程安全问题以及与其他设计模式的区别和协作。
  • 只有在合适的场景下使用建造者模式,才能充分发挥其优势并提升软件的质量。

经典建造者模式和流式建造者模式都是用于封装复杂对象创建过程的有效方式。经典建造者模式通过抽象建造者接口和具体建造者类的分离,实现了构建过程的灵活性和可扩展性。而流式建造者模式则通过链式调用的方式,提高了代码的可读性和编写的便捷性。

在选择使用哪种建造者模式时,需要根据具体的需求和场景来判断。如果需要较高的灵活性和可扩展性,可以考虑使用经典建造者模式;如果追求代码的简洁和易读性,流式建造者模式可能是一个更好的选择。

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

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

相关文章

Spring Boot 注解教程

Spring Boot 注解教程 在 Spring 和 Spring Boot 的世界里,注解(Annotations)起着至关重要的作用。它们为开发者提供了声明式编程的能力,大大简化了 Spring 应用的开发过程。在这篇博客中,我们将探讨 Spring Boot 中的…

Redux 与 Vuex:探索它们的设计思想及应用差异

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

力扣Python方法解析

1.两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按…

图像压缩神器:使用wxPython和Pillow快速压缩JPEG文件

导语: 在数字时代,我们经常处理大量的图像文件,无论是个人照片、网络图片还是工作中的设计素材。然而,随着图像数量的增多,存储和传输这些文件可能会成为一个挑战。幸运的是,我们可以利用Python编程和两个强…

【Git】项目源码迁移到另一个gitlab(保留原来提交历史记录)

目录 前情提要迁移方案IDEA远程仓库管理团队其他成员切换gitgit命令操作界面 前情提要 公司原来是自己私有部署的gitlab。有了研发云后就希望将代码推送到研发云的代码仓库上。这时候需要迁移并保留原来提交的历史记录。 迁移方案 登录新的gitlab(代码仓库)新建空白项目获取…

如何搭建selenium自动化测试框架?selenium自动化测试环境搭建(webdriver+Python框架)

一、安装Python 选择Python版本后,进入Python官方网站下载适配机型版本:http://www.python.org/ 二、安装setuptools和pip setuptools下载地址:https://pypi.python.org/pypi/setuptools pip下载地址:https://pypi.python.org/py…

突破编程_C++_设计模式(策略模式)

1 策略模式的概念 策略模式(Strategy Pattern)是 C 中常用的一种行为设计模式,它能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为模式。 在策略模式中,需…

BUUCTF----[极客大挑战 2019]HardSQL

输入1’ 单引号闭合 进行永真式判断 竟然说我是臭弟弟----八嘎(肯定是进行了过滤) 经过手法判断,过滤了,空格,and等报错注入updatexml() 报错注入顾名思义就是,通过特殊函数错误使用并使其输出错误结果来获…

性能测试能力提升 —— 线程、并发、吞吐量、TPS、QPS、响应时间

一、背景 接着上一篇的知识:性能测试能力提升-关于性能测试,本篇文章,我们将主要介绍以下几方面的知识: 线程数&并发用户数相对并发&绝对并发吞吐量TPS&QPS响应时间 二、线程数、并发用户数 线程数: 主流的性能测…

Android Studio轮播图使用失败怎么办【已解决】

Android Studio轮播图使用失败怎么办 1.在gethub上面搜索轮播图 2.选择要使用的轮播图 3.查看该轮播图的配置方法 4.复制该依赖放入build.gradle中 5.重新构建 6.使用banner 发现没有报错了 7.参考网址 https://github.com/youth5201314/banner

解读BOT攻击,探索灵活高效的防护之道

回顾早期的互联网应用,由于业务流量比较小,往往单台服务器就能满足负载需求。随着互联网的流量越来越大,单服务器已经不能满足业务需求,无论它优化得再好,都较难承受大量的访问压力。支持负载均衡的技术很多&#xff0…

微信加好友频繁会被封号吗?

微信加好友频繁会被封号吗? 微信规定,每个人每天最多可以加20个好友,但一天之内如果频繁加好友,微信可能会出现异常提示,需要暂停好友添加操作。 面对微信上突如其来的大量好友申请,一定要谨慎处理,以免被…

新增流计算计数窗口,TDengine 3.2.3.0 八大板块功能更新

自发布以来,TDengine 3.0 版本在研发人员和社区用户的共同努力下不断优化,产品的稳定性和易用性获得了大幅提升,在知轮科技的智慧轮胎系统、黑格智能 3D 打印业务、韵达快递业务、中国地震台网中心、中移物联智慧出行场景等众多企业项目中获得…

前端面试练习24.3.5

webpack相关 项目使用webpack流程 进入一个初始化好的vue项目下载安装webpack相关依赖包/插件 npm install --save-dev webpack webpack-cli webpack-dev-server安装一些相关的loader,比如vue-loader,babel-loader,css-loader等创建webpack.config.js文…

【开源】SpringBoot框架开发教学资源共享平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 类图设计3.3 数据库设计3.3.1 课程档案表3.3.2 课程资源表3.3.3 课程作业表3.3.4 课程评价表 四、系统展…

【基于springboot+Vue+Element ui的电影推荐之协同过滤算法简单实现】

基于springbootVueElement ui的电影推荐之协同过滤算法简单实现 1.基于用户的协同过滤算法的简单设计与实现1.1获取某个用户的评分矩阵1.2获取该用户与其他用户的相似度矩阵1.3获取两个用户之间的相似度并存储1.4返回推荐列表 2.基于物品的协同过滤算法的简单设计与实现2.1计算…

蓝桥杯每日一题(哈希、单调队列)

2058 笨拙的手指 二进制所有的可能保存进哈希表&#xff0c;三进制找出所有的可能判断哈希表中是否有数字。 注意一种情况就是修改完之后出现前导零。直接continue; 学到了&#xff0c;某些条件的限制不一定要在循环条件上&#xff0c;可以直接在循环体内。 #include<bi…

运维:记一次寻找定时任务并删除的经历

前言 我相信接手别人的服务器、或者在没有任何文档的情况去看自己原先的服务器,都或多或少会遇到莫名其妙的服务器独有规则。 比如你服务本身跑的好好的,突然啪的一下,没了! 什么原因导致的呢?其中,很大可能是定时任务在作祟。 原因分析 本次,我遇到的问题是:在Ubuntu系…

一分钟了解遥感中卫星、传感器、波段及数据之间的关系

感是利用卫星、飞机或其他载具上的传感器对地球表面进行观测和测量的科学技术。以下是一些常见的遥感相关术语: 卫星(Satellite):在遥感中,卫星是指绕地球轨道运行的人造卫星,其主要任务是携带各种传感器从空间中对地球表面进行观测。 传感器(Sensor):传感器是安装在卫…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:ImageSpan)

Text组件的子组件&#xff0c;用于显示行内图片。 说明&#xff1a; 该组件从API Version 10开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 ImageSpan(value: ResourceStr | PixelMap) 参数&#xff1a; 参数名参数类…