3

我有一个有多个构造函数的类。每个代表不同的用例。

public class ABC {
  public ABC(int x) {
  ...
  }
  public ABC(ArrayList<String> Stringarray) {
  ...
  }
  ..many more constructors..
}

到目前为止,构造函数重载是干净的解决方案,直到我遇到来自 java 编译器的相同擦除问题。例如,我想添加另一个最终具有相同擦除的构造函数,所以我只是选择包含一个默认参数来暂时解决,如下所示:

public ABC(ArrayList<String> stringArray) {
  …
}
public ABC(ArrayList<Integer> integerArray, boolean… sameErasureFlag) {
  …
}

但是我有一种强烈的感觉,可能有这么多的构造函数对于这个用例来说不是一个好的设计模式。也许有一个更好的解决方案或最佳实践设计模式用于这种场景。我正在查找构建器模式,但不确定这是否正确/更好。有什么建议吗?

4

6 回答 6

8

我有一个有多个构造函数的类。每个代表不同的用例。

那么简单的答案是:将每个用例变成自己独特的类。

一个类中有多个不相关的字段,并且每个“用例”只使用其中一些字段的想法清楚地表明您的类正在做太多事情

任何类或方法都应该只做“一件事”。所以,如前所述:答案是停在那里,而不是在一个类中添加更多东西:问问自己,你如何才能有意义地把它分开。

于 2021-03-19T09:40:36.823 回答
2

这取决于类究竟对参数做了什么,我们没有确切的细节,但你可以为泛型类型做的一件简单的事情是让你自己的类泛型(也许不需要应用花哨的设计模式在这种情况下):

public class ABC<T> {
    public ABC(ArrayList<T> stringArray) {
       …
    }
    …
}


ArrayList<Integer> intList = Stream.of(1, 2, 3)
                                   .collect(Collectors.toCollection(ArrayList::new));
ArrayList<String> stringList = Stream.of("a", "b", "c")
                                   .collect(Collectors.toCollection(ArrayList::new));
ABC<Integer> abc1 = new ABC<>(intList);
ABC<String> abc2 = new ABC<>(stringList);
于 2021-03-19T09:29:37.070 回答
2

我有一种强烈的感觉,可能有这么多的构造函数不是一个好的设计模式..

这取决于。

有些人喜欢构造函数,有些人喜欢其他方法,但我认为你是对的,拥有大量重载的构造函数可能阅读和维护起来很麻烦。

要考虑的一种替代方法是Static Factory Methods. 最近,许多作者建议使用静态工厂方法而不是构造函数。

您可能想要支持它们的原因有几个:

它们为您提供更好、更清晰、更直观的可读性

你不能给构造函数命名。构造函数名始终与类名相同;但是,您可能会发现使用命名很有用,因为它们将提供更清晰的可读性。

您可以构造和返回子类型

当你使用构造函数时,你不能改变构造对象的类型;但是,工厂方法可以返回派生自超类的对象这意味着您可以根据输入条件决定具体构造什么。

于 2021-03-19T12:16:39.073 回答
2

您的类是否真的实现了不同的用例,每个用例都由另一个构造函数表示?那么这就是答案

如果您只想为您的类提供不同的初始化路径,否则它们会执行相同的操作,无论您用于初始化的数据格式如何,那么拥有多个构造函数可能是正确的选择。

但是当超过一定数量的构造函数时(有的说 3 个,有的 5 个……有些极端分子甚至说 1 个),你肯定有太多的构造函数,然后你应该考虑工厂模式,就像这里建议的那样。当您考虑引入“虚拟”参数来解决擦除问题时,应该明确考虑这一点——无论你有多少构造函数。工厂模式的优点是工厂方法的签名不仅仅由参数列表决定,您还可以选择不同的名称(ABC.ofIntList()ABC.ofStringList()等等......)。

于 2021-03-19T10:10:08.290 回答
1

如果您的班级中有太多领域,我建议您的设计很糟糕。有些人可能会建议使用Builder Pattern。但我认为最好表现出对 OOP 的更多尊重,所以我认为最好将你的类分成多个类并使用Decorator Pattern

于 2021-03-19T10:42:08.987 回答
0

是的,有许多构造函数可以指出该类违反了单一责任原则。我同意 - 信息不足以做出决定。构建器模式可以工作,甚至可以抽象工厂。但是 - 考虑使用工厂方法而不是构造函数,如 J.Bloch 建议的那样:

public ABC of(ArrayList<Integer> integerArray, boolean… sameErasureFlag) {

… }

于 2021-03-19T09:46:47.140 回答