Java方法中的参数太多,第2部分:参数对象

在上一篇文章中 ,我研究了与方法和构造函数的长参数列表相关的一些问题。 在那篇文章中,我讨论了用自定义类型替换基元和内置类型以提高可读性和类型安全性。 这种方法使方法或构造函数的众多参数更具可读性,但并没有减少参数的数量。 在本文中,我将研究如何使用Parameter Object来减少方法或构造函数的参数数量。

通常,使“垃圾箱”对象耦合不相关的参数通常不是一个好主意,这些参数之间的唯一关系是它们需要传递给相同的方法或构造函数。 但是,当将相关参数作为高度内聚的对象的一部分传递给构造函数或方法时,称为Introduce Parameter Object的重构是一个不错的解决方案。 重构的用法被描述为 “自然组合在一起的参数组”。 我将在这篇文章中演示这种重构。

为了演示Introduce Parameter Object重构的效用,让我们首先来看最后一篇文章中的示例,该示例在方法调用中使用了许多Stringboolean参数。

/*** Instantiate a Person object.* * @param lastName* @param firstName* @param middleName* @param salutation* @param suffix* @param streetAddress* @param city* @param state* @param isFemale* @param isEmployed* @param isHomeOwner* @return */public Person createPerson(final String lastName,final String firstName,final String middleName,final String salutation,final String suffix,final String streetAddress,final String city,final String state,final boolean isFemale,final boolean isEmployed,final boolean isHomeOwner){// implementation goes here}

正如我在上一篇文章中所讨论的那样,这种方法对于调用者来说是乏味的,使得以错误的顺序传递参数变得非常容易,而类型安全性却很少,并且会降低代码的可读性。 幸运的是,此示例中的参数为应用Introduce Parameter Object重构提供了一些很好的机会。 “名称”参数(包括称呼和后缀)可以包含在单个全名类中。 地址参数(街道地址,城市和州)可以位于单个地址对象中。 其他参数可能不太容易分组为具有高内聚力的单个类。

使用“引入参数对象”重构的建议应用程序,由于减少了参数数量,因此前面显示的方法调用更加简单。 这显示在下一个代码清单中。

public Person createPerson(final FullName fullName,final Address address,final boolean isFemale,final boolean isEmployed,final boolean isHomeOwner){return new Person();}

上面的示例现在只有五个参数,并且更易于阅读,并且更易于客户端使用。 从键入的角度来看,它也是更安全的,因为在这种情况下几乎不可能将名称字符串与地址字符串混淆。 不幸的是,这三个布尔参数仍然有点造成潜在的混乱和云可读性。 接下来的代码清单显示FullNameAddress类的潜在实现。

FullName.java(简单)

package dustin.examples;/*** Full name of a person.* * @author Dustin*/
public final class FullName
{private final String lastName;private final String firstName;private final String middleName;private final String salutation;private final String suffix;public FullName(final String newLastName,final String newFirstName,final String newMiddleName,final String newSalutation,final String newSuffix){this.lastName = newLastName;this.firstName = newFirstName;this.middleName = newMiddleName;this.salutation = newSalutation;this.suffix = newSuffix;}public String getLastName(){return this.lastName;}public String getFirstName(){return this.firstName;}public String getMiddleName(){return this.middleName;}public String getSalutation(){return this.salutation;}public String getSuffix(){return this.suffix;}@Overridepublic String toString(){return  this.salutation + " " + this.firstName + " " + this.middleName+ this.lastName + ", " + this.suffix;}
}

Address.java(简单)

package dustin.examples;/*** Representation of a United States address.* * @author Dustin*/
public final class Address
{private final String streetAddress;private final String city;private final String state;public Address(final String newStreetAddress, final String newCity, final String newState){this.streetAddress = newStreetAddress;this.city = newCity;this.state = newState;}public String getStreetAddress(){return this.streetAddress;}public String getCity(){return this.city;}public String getState(){return this.state;}@Overridepublic String toString(){return this.streetAddress + ", " + this.city + ", " + this.state;}
}

尽管代码得到了改进,但是仍有一些问题可以改进。 特别是,具有太多参数的原始方法仍然具有三个boolean参数,可以很容易地将它们相互混淆。 尽管该方法的String参数被分解为两个新类,但这两个新类仍分别由一堆String组成。 在这些情况下,可能需要使用自定义类型来补充“ 介绍参数对象”重构。 使用我在上一篇文章中显示的自定义类型,带有太多参数的方法现在看起来像下一个代码清单中所示。

public Person createPerson(final FullName fullName,final Address address,final Gender gender,final EmploymentStatus employment,final HomeownerStatus homeownerStatus){// implementation goes here}

该方法现在具有较少的参数,并且确实具有不同类型的参数。 现在,IDE和Java编译器对于确保客户端正确使用此接口特别有用。 将自定义类型(写在最后一篇文章中)应用于FullNameAddress类会导致这些类的下两个新代码清单。

FullName.java(自定义类型)

package dustin.examples;/*** Full name of a person.* * @author Dustin*/
public final class FullName
{private final Name lastName;private final Name firstName;private final Name middleName;private final Salutation salutation;private final Suffix suffix;public FullName(final Name newLastName,final Name newFirstName,final Name newMiddleName,final Salutation newSalutation,final Suffix newSuffix){this.lastName = newLastName;this.firstName = newFirstName;this.middleName = newMiddleName;this.salutation = newSalutation;this.suffix = newSuffix;}public Name getLastName(){return this.lastName;}public Name getFirstName(){return this.firstName;}public Name getMiddleName(){return this.middleName;}public Salutation getSalutation(){return this.salutation;}public Suffix getSuffix(){return this.suffix;}@Overridepublic String toString(){return  this.salutation + " " + this.firstName + " " + this.middleName+ this.lastName + ", " + this.suffix;}
}

Address.java(自定义类型)

package dustin.examples;/*** Representation of a United States address.* * @author Dustin*/
public final class Address
{private final StreetAddress streetAddress;private final City city;private final State state;public Address(final StreetAddress newStreetAddress, final City newCity, final State newState){this.streetAddress = newStreetAddress;this.city = newCity;this.state = newState;}public StreetAddress getStreetAddress(){return this.streetAddress;}public City getCity(){return this.city;}public State getState(){return this.state;}@Overridepublic String toString(){return this.streetAddress + ", " + this.city + ", " + this.state;}
}

到目前为止,我所有的示例都是独立的public类。 我经常发现,如果我只需要一个参数对象来在同一包中的方法和构造函数之间传递信息,那么使这些参数对象类的package作用域很有用。 在某些情况下,嵌套类也可以用于这些参数对象。

优势与优势

参数对象最明显的好处是减少了传递给方法或构造函数的参数数量。 相关参数的这种封装使快速确定要传递给方法或构造函数的类型变得更加容易。 开发人员更容易理解较少的参数。

参数对象具有与自定义类型相同的优点之一:可以为方便功能向参数对象添加其他行为和特征。 例如,拥有一个Address类而不是一堆String类型可以使人们验证地址。

成本与劣势

参数对象的主要缺点是设计,实现和测试类需要一些额外的工作。 但是,这些工具非常易于编写和测试,而现代工具(如IDE和脚本语言)使这些任务中最平凡和繁琐的部分的自动化更加容易。 反对这种方法的一个更小的论点是它可以被滥用。 如果开发人员开始将不相关的参数捆绑到一个类中只是为了减少参数的数量,那并不一定会解决这种情况。 这种方法的确确实减少了参数的数量,但是没有实现提高可读性的最终目标,并且可以说这种方法的可读性更低。

结论

参数对象提供了一种很好的干净方法,可以适当地封装相关参数,以减少方法或构造函数的总参数数量。 它们易于实现,并且可以显着增强传递给方法和构造函数调用的可读性和类型安全性参数。 可以通过使用自定义类型进一步增强参数对象,如我之前的文章中所述。

参考: Java方法中的参数太多,第2部分:来自JCG合作伙伴 Dustin Marx的“ Inspired by Actual Events”博客中的Parameters对象 。

翻译自: https://www.javacodegeeks.com/2013/10/too-many-parameters-in-java-methods-part-2-parameters-object.html

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

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

相关文章

django内置服务器

单进程多线程的 多线程用来并发,各个线程之间不会阻塞,每个线程对应一个连接转载于:https://www.cnblogs.com/BlueFire-py/p/10031245.html

java mysql_Java与mysql的连接

接触编程、计算机一段时间,免不了的就要接触到,各种数据,而各种数据到了深处自然就要接触到数据的存储和调用,之前在我的文章中,已经了解到了IO流在文件中以及在TCP\IP协议中的各种传输,而慢慢的&#xff0…

Oracle 创建wims用户和表空间

/*用sys SYSDBA *//*分为四步 *//*第1步:创建临时表空间 */create temporary tablespace xxxxxxx_temp tempfile D:\app\Administrator\oradata\orcl\xxxxxxx_temp.dbf size 50m autoextend on next 50m maxsize 20480m extent management local; /*第2步&#xff1…

面试常见问题之实现bind函数

前言: 原文首发于我的博客,说实话,这半年来在各大社区看别人分享的面试题中 bind 函数已经出现 n 多次了,这次准备详细探究下 首先让我们看看 mdn 对于 bind 函数的描述是什么 语法 fun.bind(thisArg[, arg1[, arg2[, ...]]]) 参…

WIN10 开启右键 命令提示符

PowerShell强行加入右键菜单也罢了,命令提示符还默认禁用,可谓巨硬又一次智障操作。通过操作注册表可以解除这个封印: 移除 HKEY_CLASSES_ROOT\Directory\Background\shell\cmd 键中的 HideBasedOnVelocityId 然后刷新注册表,可能…

使用JUnit和Repeat注​​释编写有效的负载测试

EasyTest最近推出了一套新的注释,可帮助其用户编写有效的测试用例。 进入EasyTest的两个主要注释是: 重复 持续时间 今天,我们将讨论重复标注。 一种新的方法级别注释 重复已添加到EasyTest框架。 此批注可用于重复相同的测试多次。 在您…

mysql权限表_MySQL 数据库赋予用户权限操作表

MySQL清空数据库的操作:truncate table tablename;MySQL 赋予用户权限命令的简单格式可概括为:grant 权限 on 数据库对象 to 用户一、grant 普通数据用户,查询、插入、更新、删除 数据库中所有表数据的权利。1 grant select on testdb.* to c…

Intellij IDEA 部署Web项目,解决 404 错误

https://blog.csdn.net/eaphyy/article/details/72513914转载于:https://www.cnblogs.com/123hll/p/9329676.html

Redux源码简析

Redux核心概念 单一 store ,只能挺过getState()获取状态,不能直接修改只能通过触发 action 修改状态使用纯函数 reducers 描述action如何改变state 整个redux的实现就是围绕上面的这三点进行实现的,整个源码量不大,理解了核心概…

23种计模式之Python实现(史上最全最通俗易懂)内容整改中

第一篇 Python与设计模式:前言 第二篇(23种设计模式) 创建类设计模式(5种) 单例模式、工厂模式、简单工厂模式、抽象工厂模式、建造者模式、原型模式 结构类设计模式(7种) 代理模式、装饰器模式…

使用Apache Felix文件安装配置OSGi服务

最近有关托管服务的帖子让我想起了我值得一提的Apache Felix File Install中的一项功能。 在与Holger合作进行项目时,我从他那里了解到File Install不能仅用于管理包。 它还监视配置文件,并在托管服务各自的配置更改时更新托管服务。 文件安装还可以配置…

mysql 条件分析_数据分析之mysql

MYSQLselect 列名(全部*)计数函数:AVG(列名)返回某列的平均值COUNT()返回某列的行数(count(*)表示对表中行的数目进行计数,不管对表列中包含的是空值还是非空值。MAX()返回某列的最大值MIN()返回某列的最小值SUM()返回某列值之和distinct去重&#xff0c…

css线性渐变

此方式可以实现背景色由上往下渐变,这里加上-webkit-考虑兼容问题,若要改变渐变方向,改变top即可,如right、left、bottom效果图: 代码如下: background: -webkit-linear-gradient(top,red,black); 不带前缀&#xff0c…

scroll-view组件bindscroll实例应用:自定义滚动条

我们知道scroll-view组件作为滑动控件非常好用,而有时候我们想放置一个跟随滚动位置来跟进的滚动条,但又不想用滚动条api该怎么办呢?(当然是自己写一个呗还能怎么办[自黑冷漠脸]) 嗯,没错。自己写一个就好了…

C# -- HttpWebRequest 和 HttpWebResponse 的使用

C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebRequest 和 HttpWebResponse,来判断一个网页地址是否可以正常访问。 1.举例 class Program{static void Main(string[] args){string strUrl "https://www.baidu.com";HttpWebRequest wr…

MongoDB:GridFS删除方法删除存储桶中的所有文件

不久前,我们遇到了MongoDB GridFS的奇怪行为,这使我为MongoDB Java驱动程序创建了一个故障 单 。 今天,我在浏览器书签中找到了指向故障单的链接。 该票证目前尚未解决,因此我认为值得一小篇博文,以防其他人遇到此问题…

mysql数据库存储引擎和索引的描述_Mysql InnoDB引擎的索引与存储结构详解

前言在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据自己的需要编写自己的存储引擎。MySQL主要存储引擎的区别M…

Vue结合HTML5拖放API 实现目录拖拽~

拖放事件 dom被拖拽--->经过一些dom--->到达指定dom 被拖拽的dom:(源对象) dragstart 源对象被拖拽 drag 源对象拖拽过程中 dragend 源对象拖拽结束(drop事件后执行) 拖拽过程中经过的dom:&#xf…

【转】EMC存储移除热备盘Hot spare的方法

转载请在文首保留原文出处:EMC中文支持论坛 https://community.emc.com/docs/DOC-17382 介绍 本文将介绍如何移除Hot spare磁盘的两种方法。 更多信息 方法一: 登录Unisphere导航至Storage -> Disks从列表中找到目标hot spare盘确认Hot spare replaci…

jQuery(一)初识

jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax异步请求方式 selector: 操作(DOM)/$(selector).action(): <!DOCTYPE html> <html> <head> <meta charset"utf-8&q…