构造函数参数 – 经验法则
通常,类构造函数应该接受的参数的最大数量是多少? 我正在开发一个需要大量初始化数据的类(目前有10个参数)。 但是,具有10个参数的构造函数感觉不对。 这让我相信我应该为每个数据创建一个getter / setter。 不幸的是,getter / setter模式不会强制用户输入数据,如果没有它,对象的表征就不完整,因此无用。 思考?
有了这么多参数,就该考虑构建模式了 。 使用build()方法创建一个包含所有这些getter和setter的构建器类,该方法返回您正在尝试构造的类的对象。
例:
public class ReallyComplicatedClass { private int int1; private int int2; private String str1; private String str2; // ... and so on // Note that the constructor is private private ReallyComplicatedClass(Builder builder) { // set all those variables from the builder } public static class Builder { private int int1; private int int2; private String str1; private String str2; // and so on public Builder(/* required parameters here */) { // set required parameters } public Builder int1(int newInt) { int1 = newInt; return this; } // ... setters for all optional parameters, all returning 'this' public ReallyComplicatedClass build() { return new ReallyComplicatedClass(this); } } }
在您的客户端代码中:
ReallyComplicatedClass c = new ReallyComplicatedClass.Builder() .int1(myInt1) .str2(myStr2) .build();
请参阅Effective Java Reloaded [pdf]的第7-9页,Josh Bloch在JavaOne 2007上的演示文稿。(这也是Effective Java 2nd Edition中的第2项 ,但我没有它,因此我无法引用它。)
您可以决定何时足够,并为构造函数(或任何其他方法)使用Introduce Parameter Object 。
代码完成2建议对任何方法有相当合理的七个参数限制。
尝试为某些成员建立合理的默认值。 这将让您使用getter / setter而不必担心表征不完整。
我认为你不能说合适的数字是“七,不多”或“五”。
构造函数的一个好的经验法则是将对象传递给它的身份 ,而不是它的状态 。 传入的参数是对象存在必不可少的参数,如果没有这些参数,对象的大多数操作都可能无法实现。
如果你真的有一个具有非常复杂的自然身份的类,因此需要许多参数,那么考虑你的类的设计。
坏构造函数的一个例子是:
public NightWatchman(int currentFloor, int salary, int hapiness) {...}
在这里,NightWatchman正在构建一些默认值,几乎肯定会在短时间内发生变化。 看似有趣的是,对象以一种方式被告知其价值,然后将来以不同的方式(通过他们的制定者)将它们存在。
更好的构造函数的示例是:
public GateWatchman(Gate watchedGate, boolean shootOnSight) {...}
守望者正在观看的大门是一个存在的信息。 在课堂上我会把它标记为私人决赛 。 我选择将shootOnSight变量传递给构造函数,因为重要的是,对象始终知道是否要射杀窃贼。 在这里,身份被用作类型。
我可以有一个名为ShootingGateWatchman和PoliceCallingGateWatchman的类 – 即参数被解释为对象标识的一部分。
我建议找到参数之间的依赖关系,然后创建结构或其他类来保存它们并将它们传递给你的构造函数,而不是乍一看似乎没有相关的一堆东西。
我需要更多地了解该类的作用以及参数是什么,但是该类可能有太多的责任。 是否可以将类拆分为较小的独立类?
使用setter不能解决具有许多依赖性/参数的类的问题。 它只是将问题移到另一个地方,并不强制输入参数。
对于方法,我尝试遵循清洁代码书中的建议,每个方法(IIRC)的参数不超过3个。 对于构造函数,我可能有更多参数,因为通常构造函数将由我的dependency injection框架调用而不是由我调用。
mmyers提到的构建器模式在构建复杂对象时也是一个很好的解决方案,并且没有办法使它们变得不那么复杂。
从短期记忆的7 +/- 2规则 ,以及对程序员注意力跨度的一些悲观情绪,我通常说不超过5。 注意:我将varargs列表视为一个实体。
如果你真的被限制一次构造对象,你通常可以在简单值对象中收集相关参数并将它们传递给构造函数。 尝试确保值对象具有一定的概念意义,而不仅仅是随机的信息集合……
这取决于。
如果某些参数属于同一类型并且可以混淆,我会容忍一个相当小的数字(例如5)。
如果参数是不同类型的,那么它们不能混淆,那么我会容忍更多。 不过,十分接近极限。
如何将Param => Value Map对象传递给构造函数? 如果调用者省略了任何关键参数,请让构造函数抛出exception。
这意味着对构造函数的错误调用只会在运行时而不是编译时捕获,这是一个缺点。 但getter / setter方法有同样的问题,这应该更容易使用。
- CSS Locator with contains()使用Selenium WebDriver的InvalidSelectorException
- 无法将多个war包部署到不同的主机上,在Wildfly 8.1.0 Final上收听不同的端口?
- Request,Session和ServletContext中的属性之间的差异
- 如何使用selenium在PhantomJS中设置代理身份validation?
- 循环遍历Java中的JSON对象
- 具有HTML字符串的表格单元格不一致地呈现为多行
- IntelliJ 2018.1首选项中的“使用’ – release’选项”是什么?
- 如何在Java中使用generics类型获取类
- Guava Joiner无法使用前缀和后缀