有时,我们必须编写方法,收到许多许多参数,例如:

public void doSomething(Object objA , Object objectB ,Date date1 ,Date date2 ,String str1 ,String str2 )
{
}

当我遇到这种问题,我经常封装入参数的地图。

Map<Object,Object> params = new HashMap<Object,Object>();
params.put("objA",ObjA) ;

......

public void doSomething(Map<Object,Object> params)
{
 // extracting params 
 Object objA = (Object)params.get("objA");
 ......
 }

这不是一个好的做法、封装params入地图完全是浪费的效率。好的是,清洁签名,容易添加其他参数与最少的修改。什么是最好的实践中对这种问题?

有帮助吗?

解决方案

有效的Java, 第7章(方法),项目40(设计方法的签名小心地),布洛克写道:

有三个技术用于缩短过长的参数的清单:

  • 打破的方法纳入多种方法,每只需要一个子集的参数
  • 建立辅助课程,以保持集团的参数(通常的静态部件的类)
  • 适应生成器方式从目建筑方法调用。

更多的细节,我鼓励你买这本书,就是真正值得的。

其他提示

使用与神奇字符串键的映射是一个好主意。你失去任何编译时检查,这真的不清楚所需要的参数是什么。你需要写的非常完整的文档,以弥补它。你会在几个星期什么那些字符串是不看的代码还记得吗?如果你犯了一个错字?使用了错误的类型?你不会发现,直到运行代码。

而是使用的模型。让这将是所有这些参数的容器类。这样,你的Java守的类型安全。您也可以围绕传递对象等方法,把它收藏,等等。

当然,如果该组参数没有其它地方使用或周围通过,一个专用的模型可以是矫枉过正。还有要取得平衡,所以使用常识。

如果你有许多可选参数可以创建流利API:与方法的链取代单方法

exportWithParams().datesBetween(date1,date2)
                  .format("xml")
                  .columns("id","name","phone")
                  .table("angry_robots")
                  .invoke();

使用静态导入,您可以创建内部流畅的API:

... .datesBetween(from(date1).to(date2)) ...

这就是所谓的“引入参数对象”。如果你发现自己在经过几个地方相同的参数列表中,只要创建一个拥有所有这些类。

XXXParameter param = new XXXParameter(objA, objB, date1, date2, str1, str2);
// ...
doSomething(param);

即使你没有发现自己传递相同的参数列表中,这样的时候,那么容易重构仍然会提高你的代码的可读性,这是的总是的好。如果你在你的代码看3个月后,它会更容易理解,当你需要修复错误或添加新功能。

这是当然的一般哲学,因为你没有提供任何细节,我不能给你的更多详细的建议。 : - )

首先,我想尝试重构的方法。如果它使用许多参数也可能是太长时间任何方式。它分解既能提高代码和潜在地降低的参数的数目以每个方法。您可能还可以重构整个操作自己的类。其次,我会寻找其他情况下,我正在使用相同的参数列表的相同(或超)。如果你有多个实例,那么这些财产属于共同它可能信号。在这种情况下,创建一个类来保存参数,并使用它。最后,我想评价的参数个数是否使得它值得创建地图对象,以提高代码的可读性。我觉得这是一个私人电话 - 有疼痛各种方式与此解决方案,并且其中的权衡点可能会有所不同。对于六个参数我可能不会做。 10我可能会(如果没有其他方法制作第一)。

此构造对象时经常是一个问题。

在这种情况下,使用生成器对象模式,它工作得很好,如果你有参数的大名单,而不是总是需要所有的人。

您也可以使其适应方法调用。

这也增加可读性很多。

public class BigObject
{
  // public getters
  // private setters

  public static class Buider
  {
     private A f1;
     private B f2;
     private C f3;
     private D f4;
     private E f5;

     public Buider setField1(A f1) { this.f1 = f1; return this; }
     public Buider setField2(B f2) { this.f2 = f2; return this; }
     public Buider setField3(C f3) { this.f3 = f3; return this; }
     public Buider setField4(D f4) { this.f4 = f4; return this; }
     public Buider setField5(E f5) { this.f5 = f5; return this; }

    public BigObject build()
    {
      BigObject result = new BigObject();
      result.setField1(f1);
      result.setField2(f2);
      result.setField3(f3);
      result.setField4(f4);
      result.setField5(f5);
      return result;
    }
  }
}

// Usage:
BigObject boo = new BigObject.Builder()
  .setField1(/* whatever */)
  .setField2(/* whatever */)
  .setField3(/* whatever */)
  .setField4(/* whatever */)
  .setField5(/* whatever */)
  .build();

您也可以把验证逻辑到生成器组..()和构建()方法。

有一种称为 Parameter对象的图案。搜索结果 思想到位所有参数使用一个对象。现在,即使以后需要添加参数,只需将其添加到该对象。该方法界面保持相同。

您可以创建一个类来保存数据。需要足够有意义虽然,但比使用地图(OMG)好得多。

代码的完整*表明几件事情:

  • "数量限制的一个常规的参数大约七个。七是一个神奇的数量为人们的理解"(第108).
  • "把参数在输入-修改产出的顺序...如果几个例行程序使用类似的参数,把类似的参数在一致秩序"(第105).
  • 放状态或错误的变量的最后一次。
  • 作为 tvanfosson 所提及的,通行证只有部分的一个结构性的变量(目的)的程序的需要。这就是说,如果你正在使用的大部分结构变量的功能,那么只有通过整个结构,但注意,这促进了联到某一程度。

*第一版,我知道我应该更新。此外,很可能有一些这样的建议可能已经改变,因为第二版的编写时面向对象开始成为更受欢迎。

好做法是重构。有关这些对象是什么意思,他们也应传递给此方法?它们应该被封装成单个对象?

使用地图是清洁调用签名一个简单的方法,但那么你有另外一个问题。你需要看的方法体内,看看有什么方法需要在地图,什么是什么类型的值有按键名称或

一个更清洁的方式将组中的对象的bean的所有参数,但是这仍然没有完全解决该问题。

在这里什么是一个设计问题。拥有超过7个参数的方法,你就会开始有记忆它们代表什么,什么样的顺序,他们有问题。在这里,您将只通过调用错误的参数顺序的方法获得大量的bug。

您需要一个更好的设计应用程序的不是最好的做法,以发送大量的参数。

创建bean类,并设置所有参数(setter方法),并且该bean对象传递给该方法。

这常常是,你的类包含多个职责(即,你的类做太多)。

的指示

请参阅的单一职责原则

有关的进一步细节。

如果您传递的参数太多,然后尝试重构方法。也许是做了很多的东西,它不是想这样做。如果不是这样,那么尝试用一个类替代的参数。这样,您就可以封装在一个类实例的一切,围而不通过实例的参数。

  • 看看你的代码,看看为什么所有的这些参数是通过。有时可能重构方法本身。

  • 使用地图离开你的方法很脆弱。什么如果有人用你的方法拼错一个参数的名字,或者员额的字符串你的方法期望UDT?

  • 定义 传对象 .它将提供类型检查,至少;它甚至可能是可以执行一些验证在使用点,而不是在你方法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top