The following text is a partial translation of the original English article, performed by ChatGPT (gpt-3.5-turbo) and this Jekyll plugin:
让构造函数在封装参数之前对其进行预处理似乎是一种不好的做法。然而,很多时候确实需要这样做:对作为参数提供的对象进行一些操作,然后再将它们赋值给构造对象的属性。为此,我建议使用“prestructors”(预处理器),它可以是方法或独立的对象。
假设这是你的代码:
import java.util.List;
import java.util.Collections;
class Books {
private final List<String> titles;
Books(List<String> list) {
this.titles = Collections.unmodifiableList(list);
}
}
唯一的构造函数期望一个标题列表,这个列表被封装为this.titles
以备将来使用。它还通过JDK装饰器unmodifiableList
来防止任何意外修改。到目前为止,一切都很好。现在,我们想让我们的类更智能一些,不仅接受List
,还接受一个字符串数组:
class Books {
private List<String> titles;
Books(List<String> list) {
this.titles = Collections.unmodifiableList(list);
}
Books(String... array) {
final List<String> list = new ArrayList<>(array.length);
for (final String title : array) {
list.add(title);
}
this.titles = list;
}
}
这段代码有什么问题?那些阅读过我之前有关面向对象编程的博客文章的人肯定知道答案。首先,有两个主要构造函数,这是另一个不好的实践。其次,在第二个构造函数中有代码,这也是一个不好的想法。
以下是我通常如何重构这段代码,以解决上述两个问题:
class Books {
private List<String> titles;
Books(List<String> list) {
this.titles = Collections.unmodifiableList(list);
}
Books(String... array) {
this(Books.toList(array));
}
private static List<String> toList(String... array) {
final List<String> list = new ArrayList<>(array.length);
for (final String title : array) {
list.add(title);
}
return list;
}
}
我把这个新的静态方法toList()
称为prestructor:它仅在对象构造的瞬间使用,而且仅从次要构造函数中使用。
更好的设计方法是创建一个名为ToList
的新类,它可以以更声明性和延迟的方式完成完全相同的操作:
class Books {
private List<String> titles;
Books(List<String> list) {
this.titles = Collections.unmodifiableList(list);
}
Books(String... array) {
this(new ToList(array));
}
}
class ToList<T> implements List<T> {
private final T[] array;
ToList(T... items) {
this.array = items;
}
// All required methods of the List interface
}
ListOf
来自Cactoos是这样一个预构造器的完美示例。
Translated by ChatGPT gpt-3.5-turbo/36 on 2023-10-12 at 16:02