Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java高效编程(2):面对多个构造参数时考虑使用构建器模式

Java高效编程(2):面对多个构造参数时考虑使用构建器模式

作者头像
蒙娜丽宁
发布于 2024-11-23 07:44:32
发布于 2024-11-23 07:44:32
10200
代码可运行
举报
文章被收录于专栏:极客起源极客起源
运行总次数:0
代码可运行

Java编程中,静态工厂和构造函数都存在一个局限性:当可选参数数量较多时,它们的扩展性较差。以表示食品包装上营养成分标签的类为例,这些标签包含几个必需字段——如份量大小、每容器的份数和每份的卡路里——以及超过二十个可选字段,例如总脂肪、饱和脂肪、反式脂肪、胆固醇、钠等。大多数产品只有少数这些可选字段的值不为零。

在这种情况下,应该如何编写构造函数或静态工厂呢?传统上,程序员采用了“ telescoping constructor pattern”(逐层构造函数模式),这种模式提供了一个只接受必需参数的构造函数、一个接受一个可选参数的构造函数、一个接受两个可选参数的构造函数,依此类推,最终形成一个接受所有可选参数的构造函数。以下是这种模式的示例,为了简洁,仅显示了四个可选字段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 逐层构造函数模式 - 扩展性差! public class NutritionFacts {     private final int servingSize;  // (mL)  必需     private final int servings;      // 必需     private final int calories;      // 可选     private final int fat;           // 可选     private final int sodium;        // 可选     private final int carbohydrate;  // (g/serving) 可选      public NutritionFacts(int servingSize, int servings) {         this(servingSize, servings, 0);     }     public NutritionFacts(int servingSize, int servings, int calories) {         this(servingSize, servings, calories, 0);     }     public NutritionFacts(int servingSize, int servings, int calories, int fat) {         this(servingSize, servings, calories, fat, 0);     }     public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {         this(servingSize, servings, calories, fat, sodium, 0);     } } 

虽然这种方法在小范围内可行,但随着可选参数的增多,构造函数的数量迅速增加,导致代码难以管理和维护。

解决方案:构建器模式

为了应对这一挑战,可以采用构建器模式。这种模式允许逐步构建对象,并在创建时提供灵活性和可读性。下面是使用构建器模式重构 NutritionFacts 类的示例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class NutritionFacts {     private final int servingSize;  // (mL)     private final int servings;     private final int calories;      // 可选     private final int fat;           // 可选     private final int sodium;        // 可选     private final int carbohydrate;  // 可选      private NutritionFacts(Builder builder) {         this.servingSize = builder.servingSize;         this.servings = builder.servings;         this.calories = builder.calories;         this.fat = builder.fat;         this.sodium = builder.sodium;         this.carbohydrate = builder.carbohydrate;     }      public static class Builder {         private final int servingSize;  // (mL)         private final int servings;         private int calories = 0;        // 默认值         private int fat = 0;             // 默认值         private int sodium = 0;          // 默认值         private int carbohydrate = 0;    // 默认值          public Builder(int servingSize, int servings) {             this.servingSize = servingSize;             this.servings = servings;         }          public Builder calories(int val) {             calories = val;             return this;         }          public Builder fat(int val) {             fat = val;             return this;         }          public Builder sodium(int val) {             sodium = val;             return this;         }          public Builder carbohydrate(int val) {             carbohydrate = val;             return this;         }          public NutritionFacts build() {             return new NutritionFacts(this);         }     } } 
使用示例

使用构建器模式创建 NutritionFacts 实例变得简单且清晰:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NutritionFacts nutritionFacts = new NutritionFacts.Builder(240, 2)         .calories(100)         .fat(5)         .sodium(10)         .carbohydrate(20)         .build(); 

这种方式不仅提高了可读性,还允许你在创建对象时轻松选择性地设置参数,从而避免了构造函数数量暴增的问题。构建器模式是处理多个构造参数的理想选择,特别是在面对许多可选字段时。

- EOF -

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客起源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Effective Java】Ch2_创建销毁对象:Item2_当构造函数参数过多时考虑使用builder
静态工厂和构造函数都有一个限制:可选参数数量很大时,他们都不能很好地扩展。考虑一下这个例子:用一个类来表示袋装食品上的营养成分标签,这些标签有几个必选字段:每份的含量、每罐的份数、每份的卡路里;还有超过20个可选字段:总脂肪含量、饱和脂肪含量、转化脂肪含量、胆固醇含量、钠含量等等。大多数产品只有少数几个可选字段是非零值。
用户7886150
2020/12/15
5010
Effective Java 2.0_Item 2_中文版
静态工厂和构造函数有一个共同的限制:对于大量可选参数它们都不能很好的扩展。考虑这样一种情况:用一个类来表示包装食品上的营养成分标签。这些标签有几个字段是必须的——每份含量、每罐含量(份数)、每份的卡路里,二十个以上的可选字段——总脂肪量、饱和脂肪量、转化脂肪、胆固醇、钠等等。大多数产品中这些可选字段中的仅有几个是非零值。
Tyan
2022/05/09
2790
Effective Java 2.0_中英文对照_Item 2
Static factories and constructors share a limitation: they do not scale well to large numbers of optional parameters. Consider the case of a class representing the Nutrition Facts label that appears on packaged foods. These labels have a few required fields—serving size, servings per container, and calories per serving and over twenty optional fields—total fat, saturated fat, trans fat, cholesterol, sodium, and so on. Most products have nonzero values for only a few of these optional fields.
Tyan
2022/05/09
3430
Effective.Java 读书笔记(2)使用Builder
静态工厂和构造器都有一个限制,它们不能够很好地缩减大量地选项参数,想象一下一种情况,你的类有着很多的成员变量,有些必须填写有些可以选填,那么如果使用传统的构造方法的话,排列组合一下可以想象会有多少个构造方法出现,这样的情况不是我们所需要的,程序员们通常会使用一种名为”伸缩构造函数模式(Telescoping constructor pattern )“的办法,就是先提供必须要的选项参数作为最简单的构造方法,然后把非必须的选项参数逐渐加上去构成新的构造方法,不考虑组合的问题
Mezereon
2018/09/13
3780
当构造方法参数过多时使用builder模式
静态工厂和构造方法都有一个限制:它们不能很好地扩展到很多可选参数的情景。请考虑一个代表包装食品上的营养成分标签的例子。这些标签有几个必需的属性——每次建议的摄入量,每罐的份量和每份卡路里 ,以及超过 20 个可选的属性——总脂肪、饱和脂肪、反式脂肪、胆固醇、钠等等。大多数产品都有非零值,只有少数几个可选属性。
海仔
2019/08/06
9930
java与es8实战之一:以builder pattern开篇
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于《java与es8实战》系列 《java与es8实战》系列是欣宸与2022年夏季推出的原创系列,如标题所述,该系列从一个java程序员视角去学习和实践elasticsearch的8.2版本,目标是与大家一起掌握与elasticsearch开发相关的技能,以应对实际应用中的需求和挑战 本篇概览 纵观欣宸过往各种系列文章,开篇无外乎两种套路 第一种是对该系列的主
程序员欣宸
2022/06/19
6740
java与es8实战之一:以builder pattern开篇
java(4)-深入理解java嵌套类、内部类以及内部类builder构建构造函数六、使用 builder 模式解决构造方法参数过多的情况
  可以在一个类的内部定义另一个类,这种类称为嵌套类(nested classes),它有两种类型:静态嵌套类和非静态嵌套类。静态嵌套类使用很少,最重要的是非静态嵌套类,也即是被称作为内部类(inner)。嵌套类从JDK1.1开始引入。其中inner类又可分为三种:  其一、在一个类(外部类)中直接定义的内部类;   其二、在一个方法(外部类的方法)中定义的内部类;   其三、匿名内部类。
黄规速
2022/04/14
1.7K0
Java架构师教你写代码(二) - 使用建造者替代多参数的构造器
比如一个类,表示包装食品上的营养标签。 有些字段是必需的:净含量、毛重和每单位份量的卡路里, 还有 20 个可选字段,如:总脂肪、饱和脂肪、反式脂肪、胆固醇、钠… 大多食品只使用可选字段中的少数,且非零值。
JavaEdge
2021/02/22
6800
Java架构师教你写代码(二) - 使用建造者替代多参数的构造器
Effective Java(一)
对于类而言,为了让客户端获取它自身的一个实例,最传统的方法就是提供一个公有的构造器。还有一种方法,也应该在每个程序员的工具箱中占有一席之地。类可以提供一个公有的静态工厂方法( static factory method ),它只是一个返回类的实例的静态方法。下面是一个来自 Boolean(基本类型 boolean 装箱类)的简单示例。这个方法将 boolean 基本类型值转换成了 Boolean 对象引用:
Remember_Ray
2020/08/03
6780
《Effective Java》读书笔记(一)之创建和销毁对象
最近在研读《Effective Java》一书,读书不做点笔记,感觉很容易就忘掉,于是用本篇博客来记录阅读此书的笔记。 郑重声明: 由于是《Effective Java》一书的笔记,所以大部分内容基本来自此书,还有一小部分是自己的理解。
老马的编程之旅
2022/06/22
3730
效率编程 之「创建和销毁对象」
但是很遗憾,在标准的 JDK 中,并没有提供类似的静态工厂方法。不过,我们可以通过在项目中引入谷歌发布的Guava,使用类似上述的静态工厂方法。当然,静态工厂方法也不是尽善尽美的,也有其缺点:
CG国斌
2019/05/26
5370
建造者模式
将一个复杂的对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。 ——《设计模式:可复用面向对象软件的基础》
mingmingcome
2021/11/29
3860
建造者模式
effective Java 创建和销毁对象篇
小伙伴们好呀,我是 小羊 ,今天来和大家分享下 《Effective Java》这本书的 第2章 —— 创建和销毁对象 。
Java4ye
2024/02/14
3050
effective Java 创建和销毁对象篇
《Effective Java 》系列一
编写实例受控类有几个原因。实例受控使得类可以确保他是一个Singleton或者是不可实例化的。他还使得不可变类可以确保不会存在两个相等的实例。
高广超
2018/12/12
8630
Java中的静态内部类_Effective Java 2.0_Item 2知识点
在Java中有静态代码块、静态变量、静态方法,当然也有静态类,但Java中的静态类只能是Java的内部类,也称为静态嵌套类。静态内部类的定义如下:
Tyan
2022/05/09
3310
如何使用建造者模式构造复杂对象?
『建造者模式』是一种简化复杂对象构建过程的设计模式,他的核心夙愿是:把对象的构建和表述分离。
Single
2021/04/22
6910
构建者模式?学会了,可以造房子?
在软件工程领域,设计模式是一套通用、可复用的解决方案,用于解决在软件设计过程中产生的通用问题。它不是一个可以直接转成源码的设计,是一套开发人员在软件设计过程中应当遵循的规范。也就是说没有设计模式,软件依旧可以开发,只是后期维护可能变得不那么轻松。设计模式就是为了简化你的维护成本提升性能而设计的,不同的设计模式适用场景各异,具体的结合实际场景对待。
啃饼思录
2021/11/02
4270
同学你根本不懂 Builder 设计模式!
在日常开发中,发现有些同学喜欢用 lombok 的 @Builder 注解,主要原因是喜欢使用链式编程。 但如果一个方法里面多个对象都使用 builder 模式,每个对象构建都放在一行使用,代码过长;如果每个属性设置都滑换行,占的行数就很多,导致可读性降低。
明明如月学长
2023/03/30
1.5K0
同学你根本不懂 Builder 设计模式!
JVM性能优化系列-(4) 编写高效Java程序
正常情况下,如果构造器参数过多,可能会考虑重写多个不同参数的构造函数,如下面的例子所示:
码老思
2023/10/19
2640
笔记《Effective Java》01: 创建和销毁对象
《Effective Java》这本书可以说是程序员必读的书籍之一。这本书讲述了一些优雅的,高效的编程技巧。对一些方法或API的调用有独到的见解,还是值得一看的。刚好最近重拾这本书,看的是第三版,顺手整理了一下笔记,用于自己归纳总结使用。建议多读一下原文。今天整理第一章节:创建和销毁对象。
有一只柴犬
2025/01/24
860
笔记《Effective Java》01: 创建和销毁对象
推荐阅读
相关推荐
【Effective Java】Ch2_创建销毁对象:Item2_当构造函数参数过多时考虑使用builder
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验