简而言之,静态工厂很酷并且有其用途,但有些 API 陷入了到处使用它们的陷阱,即使它们没有增加价值而只是增加了复杂性。
静态工厂在 Java 中运行良好的一个例子是 EnumSet,它有许多命名的构建器,不能自然地实现为重载的构造器。
例如,即使它们具有相同的论点,它们也不会做同样的事情。
EnumSet.of(E1, E3);
EnumSet.range(E1, E3);
EnumSet 还根据枚举中元素的数量返回两种不同的实现。
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
不幸的是 EnumMap 并没有做类似的事情,所以只有一个实现。
.1。一方面,您可以获得更好的类型推断。例如参见番石榴的
所以番石榴有类似的方法
List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();
在 Java 7 中只是
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();
Map<KeyType, LongishValueType> map = new LinkedHashMap<>();
这更短,您不需要学习任何新方法,如果您不需要对类型进行双重检查,您可以执行以下操作。
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList();
Map<KeyType, LongishValueType> map = new LinkedHashMap();
在番石榴中,你有
Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");
内置方法在哪里
Set<Type> copySet = new HashSet<String>(elements);
List<String> theseElements = Arrays.asList("alpha", "beta", "gamma");
如果您<String>
从 HashSet 中删除,您将失去类型安全性,但鉴于大多数体面的 IDE 会为您自动完成此代码,您实际上不会保存任何输入。
.2. 作为该类的设计者,您可以稍后更改使用静态方法返回的内容。
我会说 YAGNI,实际上很难透明地显着改变实现。您不太可能在无需重新构建或重新测试代码的情况下更换具有完全向后兼容性的替代品。
.3. 处理构造函数继承是很痛苦的,特别是如果你必须预先计算一些东西。
这是真的,但很少见。对于这种情况,我通常有一个用于复杂构造的构建器类,单独的因子方法不能解决问题。
值得考虑的是,Java 库中的大多数类都使用构造函数而不是静态工厂。我能想到的唯一使用构造函数的类,但后来在可能的情况下改为使用静态工厂是自动装箱包装类。知道调用哪个工厂方法的复杂性被语言隐藏了。
鉴于 Java 的当前功能,似乎没有理由将构造函数公开......永远。友好的、私人的、受保护的都可以,但公开的不行。
仅仅因为你可以做某事并不意味着它是个好主意。
例如,您可以将所有的类、方法和变量设置为 1 或 2 个字符长(您永远不需要使用 3 个字母或更长的名称,有些人认为这样做更好),但这并不是一个好主意。
顺便说一句,如果您查看了常见的 UNIX 命令,很多都是两个字符长。;)
似乎为创建对象提供公共静态方法几乎总是一个更好的主意。
除非你更喜欢简单而不是让你的代码变得不必要的复杂。
我从来没有在任何地方看到过这种做法被法令或写下来?
我也没有。可能是因为这不是一个好主意。恕我直言。
除了可能不是我错过的超级干燥之外,还有其他用例吗?
您没有说明这样做的充分理由,这就是不为我这样做的充分理由。;)