Java方法参数太多怎么办—Part 2—引入参数对象,javapart

目录

自定义类型

引入参数对象

本文是这个系列的第二篇文章,介绍了通过引入参数对象应对参数过多的问题。如果你也希望参与类似的系列文章翻译,可以加入我们的Android开发 和 技术翻译 小组。

在前一篇文章中,我关注了一些关于构造函数或方法参数过多的问题。文中我讨论了用自定义类型代替基本、内置类型以获得良好的可读性和安全性。然而这并不能减少参数的数量。这次,我将用参数对象方法给构造函数和方法的参数“瘦身”。

通常你会看到一组特定参数,它们关系紧密并且总是一起传给方法或构造函数,有可能好几个函数都使用这一组参数。这些函数可能属于同一个类,也可能属于不同的类。

这时,《重构》这本书中介绍的“引入参数对象”的方法能很好地解决问题。该方法可以描述为运用一个对象封装这些参数,再以该对象取代他们。本文就是要演示这一“重构”。

为演示好“引入参数对象”这一重构方法,我们首先看下上篇文章曾使用过的代码示例。

/**

* 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

}

前面说过,这种传统方法对调用者来说非常乏味。不但因为没有类型安全保证导致传参时容易搞混,而且代码可读性也不是很理想。幸运的是,可以通过“引入参数对象”方法重构示例代码。“names”型参数能合并写进一个“FullName”类,同理”address”型参数也一样。其他剩余参数因为相互联系不那么紧密没法合并到一个新的类中。

在引入参数对象重构后参数数量减少了,方法调用相比以前也变得更加简单。这将在下面的代码中得以体现。

public Person createPerson(

final FullName fullName,

final Address address,

final boolean isFemale,

final boolean isEmployed,

final boolean isHomeOwner)

{

return new Person();

}

上面的示例中只有5个参数,这意味着可读性更强和调用也更方便。从类型角度看也更为安全,因为不会将名字和地址类型的字符串混淆。遗憾的是,三个布尔型参数依然存在这种隐患。下面代码展示了FullName 和Address类:

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;

}

@Override

public 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;

}

@Override

public String toString()

{

return this.streetAddress + ", " + this.city + ", " + this.state;

}

}

尽管代码得到了改进,仍然有一些问题有待结局。尤其是原来的方法参数包含了3个布尔类型,彼此之间很容易混淆。尽管字符串类型参数被重构到了两个新类,但是这两个类中还是包含了很多的字符串。这种情况就需要为引入的参数对象用自定义类型重构。使用上篇中展示的自定义类型,重构以后的参数如下面代码所示:

public Person createPerson(

final FullName fullName,

final Address address,

final Gender gender,

final EmploymentStatus employment,

final HomeownerStatus homeownerStatus)

{

// implementation goes here

}

现在方法参数个数变少了,并且类型各不相同。IDE和JAVA编译器能很有效的确保接口被正确使用。在上面示例中使用 FullName 和Address类,重构以后的代码如下:

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;

}

@Override

public 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;

}

@Override

public String toString()

{

return this.streetAddress + ", " + this.city + ", " + this.state;

}

}

现在,所有的示例都使用了独立的公共类。如果参数对象类位于同一个包的作用域中,就能将参数对象用于方法和构造函数之间传递信息,即使只能达成这一点也是非常有用的。另外在一些情况下,嵌套类也能当参数对象使用。

引入参数对象的好处与优点

最明显好处在于参数对象减少了构造函数或方法的传参数量。相关的参数一起封装更容易确定传递给构造函数和方法的是什么类型的参数。参数数量减少带给开发者的好处是显而易见的。

参数对象跟上篇文章讨论过的自定义类型有一个相同的好处:可以方便地为参数对象添加额外的行为和特征。 如用一个Address类来验证地址信息,而不是使用一堆字符串。

引入参数对象的代价与缺点

参数对象的主要缺点是需要额外的工作来设计、实现和测试相关类。但是,如果我们借助IDE和脚本语言,其中大量繁琐的步骤都能自动完成。当然,关于参数对象还有一个更小的争论:参数对象可能被滥用。如果一个开发者纯粹为了减少参数数量,把联系不紧的几个参数强捆在一个类中这肯定是行不通的,在可读性上甚至适得其反。

总结

参数对象通过恰当封装联系紧密的参数来减少方法和构造函数的参数数量。它们易于实现,能显著提高方法和构造函数在参数传递时的可读性和安全性。正如我上篇文章所说,参数对象如果结合自定义类型等一起使用效果会更好。

原文链接: dzone 翻译: Wld5.com - 韩远青

译文链接: http://www.wld5.com/6600.html

[ 转载请保留原文出处、译者和译文链接。]

java.函数参数太多,Java方法参数太多怎么办—Part 2—引入参数对象,javapart相关推荐

  1. java set 包含_Java Set.contains()方法:判断Set集合是否包含指定的对象

    Java 集合类中的 Set.contains() 方法判断 Set 集合是否包含指定的对象.该方法返回值为 boolean 类型,如果 Set 集合包含指定的对象,则返回 true,否则返回 fal ...

  2. java 函数 微秒_在Java中以微秒为单位解析时间

    我在解析2013-01-09 09:15:03.000000格式的Java时间字符串时遇到问题. 在我的数据中,最后三个数字始终为0(表示输入字符串仅具有毫秒精度),因此我将此格式传递给SimpleD ...

  3. 笔记一:java重写理解,如果子类方法名与父类方法名相同,但是参数不同,会报错吗

    一.重写概念: 发生在父类与子类之间 方法名相同 参数相同(类型,数量,顺序) 返回值类型相同或是父类的子类 访问控制修饰符的权限不能小于被重写的方法的 二.如果方法名相同,参数不同,会发生什么 这种 ...

  4. java 函数名相同_下列方法不属于java.lang.Math类的有(方法名相同即可)【 】...

    36. ____ directly affect the fitness and ability of a seafarer to perform watchkeeping duties.( 当代经济 ...

  5. Java执行引擎工作原理:方法调用

    Java执行引擎工作原理:方法调用 方法调用如何实现 函数指针和指针函数 CallStub源码详解 Git链接(有HotSpot源码) 1 方法调用如何实现 计算机核心三大功能:方法调用.取指.运算 ...

  6. java基础学习(一)方法

    1 方法的定义和调用 注意事项 方法定义的先后顺序无所谓. 方法定义必须是挨着的,不能在一个方法的内部定义另一个方法. 方法定义之后,自己不会执行:如果希望执行,一定要进行方法的调用. 如果方法有返回 ...

  7. 如何优化java反射,如何有效地使用Java反射

    反射是一种内置机制,用于在执行时对Java程序进行内省.它可以用来检查.修改和转换Java程序,而不会影响现有代码.这个强大的特性可以用来扩展程序的功能,在运行时检查类或对象的内部结构.本文试图探究其 ...

  8. java方法带参数返回值_Java方法中的参数太多,第6部分:方法返回

    java方法带参数返回值 在当前的系列文章中,我正在致力于减少调用Java方法和构造函数所需的参数数量,到目前为止,我一直专注于直接影响参数本身的方法( 自定义类型 , 参数对象 , 构建器模式 , ...

  9. Java方法01 方法(函数)定义、调用、值传递、重载、命令行传递参数

    Java 方法的定义.调用.值传递.重载.命令行传递参数 1. 什么是方法? 2. 方法的定义和调用 3. 值传递和引用传递 4. 方法的重载 5. 命令行传递参数 6. 可变参数(输入参数的数量不确 ...

最新文章

  1. 计算机模拟组装测试题一,江苏专转本计算机模拟自测试题(一)
  2. 博客会被搬去csdn
  3. [转]XNA 3.1 转换到 XNA4.0 的备忘录
  4. UIAutomator2
  5. 智能实验室-CHM浏览器(CHM Explorer) 2.0.0.200
  6. Python模块:配置文件解析器configparser
  7. 5月8号--华为正式推出新企业标识
  8. Java开源项目Hibernate获得成功的十大理由
  9. suitecrm查询功能去掉统配符%
  10. 2022年消闲设施行业研究报告
  11. CSS:border的属性
  12. VueX 以及axios
  13. Ovftool安装导出vsphere虚拟机
  14. 推荐2个国外免费网盘
  15. Vue报错-npm ERR,missing script: serve npm ERR, A complete log of this run can be found in:
  16. 享受知识饕餮盛宴,尽在2014年课程
  17. 弘辽科技:淘宝如何提升店铺流量?需要准备什么?
  18. MindSpore:环境问题案例
  19. 关于img标签中的alt和title属性作用的说明
  20. html分类价格表页面

热门文章

  1. 【2018年更新】Sublime text 3安装教程(Windows版本)
  2. Calling handler.OnEndpointsUpdate报错原因
  3. imageView的contentMode
  4. hdu1394 Minimum Inversion Number 线段树和树状数组
  5. HTML5 随机弹跳的小球
  6. Design Pattern in Java[Challenge 2.1]
  7. [概统]本科二年级 概率论与数理统计 第七讲 期望、方差与相关性
  8. Bochs调试Linux内核5 - 启动过程调试 - 认识Bootsect.S
  9. VS2019 开发第一个Windows驱动程序
  10. 一些jquery 常用实例图解