Java对象构造函数变化时的最佳实践

4
我正在上一门课程,其中根据新的 API 集成添加了许多参数。
例如,以前我的一个类只有 4 个参数:
Integer a;
String b;
Map<String, String> c;
List<Integer> e.

所以构造函数是:
public SampleClass(Integer a, 
                   String b, 
                   Map<String, String> c,      
                   List<Integer> e) 
{
    this.a = a;
    this.b = b;
    this.c = c;
    this.e = e;
}

几个团队在他们的代码中使用了这个构造函数与我的API集成。 过了一段时间,这个类添加了一个新参数。即:
Double d;

所以我添加了一个新的构造函数:
public SampleClass(Integer a,
                   String b,
                   Map<String, String> c,
                   List<Integer> e,
                   Double d)
{
    this.a = a;
    this.b = b;
    this.c = c;
    this.e = e;
    this.d = d;
}

我将之前的构造函数标记为已弃用。我没有移除之前的构造函数,因为如果移除的话客户端的代码会出现问题。
随着新参数的添加,我现在有了包含5个参数的构造函数。
在处理这种情况时,是否有最佳实践来弃用/移除构造函数,以避免出现这种情况?

1
在当前类中使用重载构造函数,采用“建造者模式”。 - Hosseini
可能是将许多参数传递给方法的最佳实践?的重复问题。 - Joe
这取决于参数的含义。如果不是必要的话,你可以保留旧的构造函数和旧的功能。 - Nico Schertler
1
我认为应该使用建造者模式 - Necromancer
1
最重要的是要有清晰且记录完备的API演进策略。因此,无论您选择哪种方式,都需要在遵循它方面保持一致,并对其进行文档化。 - biziclop
显示剩余2条评论
3个回答

4

将旧构造函数更改为:

public SampleClass(Integer a, 
                   String b, 
                   Map<String, String> c,      
                   List<Integer> e) 
{
    this.a = a;
    this.b = b;
    this.c = c;
    this.e = e;
}

to

public SampleClass(Integer a, 
                   String b, 
                   Map<String, String> c,      
                   List<Integer> e) 
{
    //Zero is passed as a default value, but you can pass anything you want
    this(a,b,c,e,0);
}

这样做将在幕后调用新的功能。
但是,您并没有提供关于旧功能应得到何种程度支持的足够信息。如果完全不需要支持旧功能,则应从代码中删除它。这样,您将强制API用户分析更改内容并连接新的构造函数。
如果您不这样做,他们会继续使用旧的功能,因为程序员很懒 :-)

1
这与懒惰无关。当您发布API时,您做出了承诺。履行该承诺是您的责任。 - biziclop
是的,但如果API必须更改并且确实更改了,程序员应该负责并分析更新到新版本时发生了什么变化。实际上,如果代码编译并通过测试,我们大多数人会简单地假设没有任何变化。而@Deprecated对此几乎没有作用:-D因此,如果更改出于某种原因至关重要,则从API中删除方法是表示用户应该分析发生了什么变化以及为什么的好方法。如果他们不想这样做,因为他们信任API本身,他们可以随时选择不更新,代价是无法获得新功能、变化等。这就是生活。 - Kelevandos
1
你只期望在主版本更改时进行强制性的API更改,这是惯例。正如我在另一条评论中所说,重要的是你有一个非常清晰的政策来处理这种情况。 - biziclop

0

遵循开闭原则将是有益的。当需要新功能时,最初编写的类不应被修改,而应该从它派生另一个类来扩展其功能。


但是随着新参数逐渐添加,不会创建新的类吗?管理所有这些类不会很困难吗? - SIDDHARTH J MEHTA

-2

为什么不使用可变参数构造函数呢?这样你就可以将任意数量的参数传递给构造函数。

例如:

public double average( double... numbers ){

       double total = 0.0; // initialize total

      // calculate total using the enhanced for statement
      for ( double d : numbers )              
         total += d;                          

      return total / numbers.length;
   } // end method average

答案与问题不匹配。 - Necromancer
请详细说明。在我看来,它是匹配的。 - rootExplorr
2
构造函数的属性并不总是双倍的。如果您想要添加**int[]**作为新属性,您会怎么做? - Necromancer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接