我最近发现了一种在Google Guava和Project Lombok中创建对象的新实例的有趣方法:隐藏静态创建方法背后的构造函数。这意味着您不是new HashBiMap()
,而是HashBiMap.create()
。
我的问题是为什么?隐藏构造函数有什么好处?对我来说,我认为这样做绝对没有优势,它似乎打破了基本的对象创建原则。自开始以来,您使用new Object()
创建了一个对象,而不是某些Object.createMe()
方法。这几乎就像为了创建方法而创建一个方法。
这样做会有什么好处?
答案 0 :(得分:27)
为什么您可能更喜欢静态工厂方法而不是公共构造函数,原因有很多。您可以阅读Effective Java, Second Edition中的第1项进行更长时间的讨论。
EnumSet.of(E)
将返回不同的类型,如果枚举类型包含许多元素(在此特定情况下为编辑:,则会改善常见情况的性能) enum没有很多元素)Integer.valueOf(x)
默认情况下,如果x
介于-128和127之间,则会使用相同的值x
多次调用返回相同的对象实例。java.util.concurrent.Executors
。Collections
中的静态方法隐藏了许多类型。他们可以创建许多公共类,而不是拥有许多静态方法的Collections
类,但对于熟悉或记住该语言的新手来说,这将更难。 List<String> strings = new ArrayList<String>()
而不是在Guava中键入List<String> strings = Lists.newArrayList()
(newArrayList
方法是通用方法,并且推断了泛型类型。)对于HashBiMap
,最后一个原因是最有可能的。
答案 1 :(得分:7)
这通常是因为create()
方法实际实例化的类可能与调用方法的类型不同。即工厂模式,其中create()
方法返回适合给定当前上下文的特定子类。 (例如,当currrent环境是Windows时返回一个实例,而当它是Linux时返回另一个实例)。
答案 2 :(得分:6)
与构造函数不同,静态方法可以具有方法名称。这是我最近写的一个有用的课程:
/**
* A number range that can be min-constrained, max-constrained,
* both-constrained or unconstrained.
*/
public class Range {
private final long min;
private final long max;
private final boolean hasMin;
private final boolean hasMax;
private Range(long min, long max, boolean hasMin, boolean hasMax) {
// ... (private constructor that just assigns attributes)
}
// Static factory methods
public static Range atLeast (long min) {
return new Range(min, 0, true, false);
}
public static Range atMost (long max) {
return new Range(0, max, false, true);
}
public static Range between (long min, long max) {
return new Range(min, max, true, true);
}
public static Range unconstrained () {
return new Range (0, 0, false, false);
}
}
你不能仅使用构造函数来执行此操作,因为atLeast
和atMost
将具有完全相同的签名(它们都需要一个长)。
答案 3 :(得分:3)
这称为Factory方法模式。工厂属于班级本身。 Wikipedia describes it pretty well但这里有几个片段。
工厂方法在工具包和框架中很常见,其中库代码需要创建类型的对象,这些类型可以由使用框架的应用程序进行子类化。
并行类层次结构通常要求来自一个层次结构的对象能够从另一个层次结构创建适当的对象。
答案 4 :(得分:0)
SomeClass.create()
可以从缓存中提取实例。如果没有一些恶作剧,new SomeClass()
就不会这样做。
create()
也可以返回SomeClass
的任意数量的实现。基本上是一种工厂类型的交易。
答案 5 :(得分:0)
虽然不适用于此特定代码示例,但将构造函数隐藏在静态方法后面的做法是Singleton Pattern。当您想要确保在整个过程中创建并使用该类的单个实例时,可以使用此方法。
答案 6 :(得分:0)
使用此工厂方法模式有很多原因,但Guava使用它的一个主要原因是它允许您在创建新实例时避免使用类型参数两次。比较:
HashBiMap<Foo, Bar> bimap = new HashBiMap<Foo, Bar>();
HashBiMap<Foo, Bar> bimap = HashBiMap.create();
与构造函数不同,Guava还充分利用了工厂方法可以拥有有用名称这一事实。考虑ImmutableList.of
,ImmutableList.copyOf
,Lists.newArrayListWithExpectedSize
等
它还利用了工厂方法不一定要创建新对象的事实。例如,ImmutableList.copyOf
,当给出一个本身为ImmutableList
的参数时,将返回该参数而不是进行任何实际复制。
最后,ImmutableList
的工厂方法返回ImmutableList
的(非公开)子类,例如EmptyImmutableList
,SingletonImmutableList
和RegularImmutableList
,具体取决于参数
构造函数无法实现这些功能。
答案 7 :(得分:0)
我有一个非常有趣的理由隐藏构造函数检查它,如果有任何其他替代方法可以让我知道
cell.myCustomLabel.attributedText = boldSearchResult(mySearchText, resultString: textForBolding)
答案 8 :(得分:0)
null