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

品读 Java 经典巨著《Effective Java》90条编程法则,第2条:遇到多个构造器参数时要考虑使用构建器

《Effective Java》是由 Joshua Bloch 撰写的经典书籍,提供了 Java 编程中的最佳实践和建议。在书中的第2条建议“遇到多个构造器参数时要考虑使用构建器”,主要是为了处理构造器参数过多时的设计问题。这条建议的主要目的是简化构造器的使用,增加代码的可读性和维护性。

了解重叠构造器模式

假设我们要设计一个Pizza类,用于表示不同类型的比萨。比萨可以有不同的配料、大小和类型(例如,薄底或厚底)。如果我们使用构造器来处理这些变体,可能会遇到以下问题:

public class Pizza {private String size;         // 比萨的大小,必需参数private String crustType;    // 比萨的底部类型,可选参数private boolean hasCheese;  // 是否有奶酪,可选参数// 包含必需参数的构造器public Pizza(String size) {this.size = size;this.crustType = "Regular";this.hasCheese = false;}
}

目前,这个Pizza类只有一个构造器用于生成一个标配版的Pizza,它仅接受size作为必需参数,并将其他属性设置为默认值。如果我们需要创建不同底部类型的Pizza,就必须添加一个新的构造器:

// 包含必需参数 size 和可选参数 crustType
public Pizza(String size, String crustType) {this.size = size;this.crustType = crustType;this.hasCheese = false;
}

如果我们需要添加奶酪,就需要生成一个全参构造器来满足需求。随着配料、大小和底部类型的组合增多,每种组合都需要一个新的构造器,这就会导致重叠构造器模式的出现。

然而在重叠构造器模式下,当一个类有多个参数,每个构造器接收不同的参数组合,构造器的数量会随着可选参数的增加迅速增加,导致代码难以维护。

使用构建器模式优化

为了避免重叠构造器模式产生的副作用,我们可以使用构建器模式来优雅地处理具有多个可选参数的类。构建器模式允许我们使用一个灵活的构建器类来设置对象的各个属性,而不是依赖于多个构造函数,这种模式适用于构建复杂的对象,特别是当对象有许多可选参数时,可以通过建造者模式来简化对象的创建过程。

具体来说,构造器模式是建造者模式(Builder Pattern)的一个常见实现,这种实现通常引入一个嵌套的 Builder 类来辅助构建对象。Builder 类包含一系列 setter 方法用于设置对象的各个部分,并提供一个 build() 方法来生成最终的对象。这个模式特别适用于构建复杂对象时,参数较多或者有多个可选项的情况。

对上述本文例子使用构建器模式的优化如下:

  1. 使用构建器模式重写Pizza类:

    public class Pizza {private String size;         // 必需参数private String crustType;    // 可选参数private boolean hasCheese;  // 可选参数// 私有构造函数private Pizza(Builder builder) {this.size = builder.size;this.crustType = builder.crustType;this.hasCheese = builder.hasCheese;}// 内部构建器类public static class Builder {private final String size; // 必需的参数private String crustType = "Regular"; // 默认值private boolean hasCheese = false; // 默认值public Builder(String size) {this.size = size;}public Builder crustType(String crustType) {this.crustType = crustType;return this;}public Builder hasCheese(boolean hasCheese) {this.hasCheese = hasCheese;return this;}public Pizza build() {return new Pizza(this);}}// getters
    }
    
  2. 使用构建器的build()方法创建Pizza对象:

    Pizza pizza = new Pizza.Builder("Large").crustType("Thin").hasCheese(true).build();
    

通过构建器模式,我们避免了重叠构造器模式的缺陷,得到了一个更灵活、更易于维护的解决方案。构建器模式使得创建对象时更加直观,能够清晰地指定哪些参数是必须的,哪些是可选的,且能够轻松添加、删除或修改参数。

构建器模式的优势

优势一:构建过程与表示的分离

在构建器模式中,Builder 类负责处理所有与对象构建相关的逻辑,而 Pizza 类只专注于存储数据。这与实际的对象类分开,使得对象类的实现更专注于其核心职责,而不需要处理复杂的构建过程,简化了复杂对象的创建过程。

优势二:支持链式调用

Builder类中的每个设置方法都返回 Builder 对象本身:

public Builder crustType(String crustType) {this.crustType = crustType;return this;
}

这种实现可以连续调用多个方法,提升代码的简洁性和可读性,并且可以按需设置,这样,调用方可以一步步构建对象而不必关心每一步如何影响对象的创建。

优势三:与不可变对象结合时,构建器模式能确保创建的对象在构建后保持不可变性

在构建器模式下,类的构造器通常被设置为私有的,调用方只能通过类内部的 Builder.build() 方法来创建实例。这种方式确保了对象只有在构建完成时才会被创建,避免了中途状态的不一致。结合不可变对象(详见第17条)的设计,所有字段在构造时进行初始化且不可变,这进一步保障了对象在创建后的稳定性和一致性,确保了对象的完整性,并且使得对象在多线程环境中更具安全性。


http://www.mrgr.cn/news/24787.html

相关文章:

  • 1,修改图片后缀名 2,重新按顺序重命名图片 python实测有效
  • 基于SpringBoot+Vue+MySQL的实训管理系统
  • C++ 互斥锁、条件变量的基础使用
  • 初始Linux 和 各种常见指令
  • 杀毒软件 | Malware Hunter v1.189.0.816 绿色版
  • 算法知识点————背包问题【动态规划】【打家劫舍】
  • 文件IO编程
  • 鸿蒙交互事件开发04——手势事件
  • 从头开始嵌入式第三十八天(数据结构 双向链表)
  • C:字符函数与字符串函数-学习笔记
  • 继图书管理项目遗留的问题修改
  • 谷歌账号登录的时候需要手机验证,但是验证的手机号码已经注销了怎么办?
  • 思维导图神器!四款高效工具助你职场逆袭
  • 【c++】类和对象详解
  • 网络编程day05(循环服务器、并发服务器)
  • Vue3+TS项目pinia使用优化在stores目录下新建index.ts
  • GEE 将本地 GeoJSON 文件上传到谷歌资产
  • 异步编程的实现方式
  • #include <netinet/in.h>
  • Reduce:一款开源的短网址平台!!【送源码】