对象的创建:构造函数或静态工厂方法
Posted
技术标签:
【中文标题】对象的创建:构造函数或静态工厂方法【英文标题】:Creation of Objects: Constructors or Static Factory Methods 【发布时间】:2011-06-04 18:38:14 【问题描述】:我正在学习Effective Java,而我的一些我认为是标准的东西在书中没有建议,例如创建对象,我的印象是构造函数是最好的方法这样做和书籍说我们应该使用静态工厂方法,我不能少一些优点和缺点,所以我问这个问题,这里是使用它的好处。
优点:
静态工厂方法的一个优点是,与构造函数不同,它们 有名字。 静态工厂方法的第二个优点是,与构造函数不同, 每次调用它们时都不需要创建新对象。 静态工厂方法的第三个优点是,与构造函数不同, 它们可以返回其返回类型的任何子类型的对象。 静态工厂方法的第四个优点是它们减少了冗长 创建参数化类型实例。
缺点:
仅提供静态工厂方法的主要缺点是 没有公共或受保护构造函数的类不能被子类化。 静态工厂方法的第二个缺点是它们不是 很容易与其他静态方法区分开来。
参考:Effective Java,Joshua Bloch,第 2 版,第 5-10 页
我无法理解第四个优势和第二个劣势,如果有人能解释这些观点,我将不胜感激。我还想了解如何决定使用构造函数还是静态工厂方法来创建对象。
【问题讨论】:
恕我直言,它归结为复杂性:如果您的代码不会被除您之外的任何人扩展,您是否需要创建更多复杂性? 即使没有其他人打算扩展代码,如果你在几个月后回来做维护/错误修复等,它仍然需要很容易理解 那么,说构造函数不会创建复杂性而静态工厂方法会足够公平吗?我试图了解哪种方式会带来更多的复杂性? 【参考方案1】:优势4:使用构造函数时,你有
Foo<Map<Key, Value>> foo = new Foo<Map<Key, Value>>();
对
Foo<Map<Key, Value>> foo = Foo.createFoo(); // no need to repeat
这个优势将在 Java 7 中消失,届时将引入菱形语法
缺点 2. 您无法轻易判断给定的 static
方法是用于构造函数还是用于其他用途。
至于如何选择 - 没有单一的配方。您可以在给定一个用例的情况下权衡上述所有优点和缺点,但大多数情况下,这只是一个由经验驱动的决定。
【讨论】:
Bozho:对于缺点 2,您能否提出一个用例,即不知道给定的静态方法是否用于构造函数会导致重大问题?我只是想了解危害会产生什么影响以及为什么将其称为劣势? @Rachel:Foo
类中的静态方法 getFoo()
会做什么?创建并返回一个新的Foo
?还是返回Foo
的子实例?甚至是单例实例?等等。缺点 2 可以通过选择方法名称来监督,例如 createFoo()
、getChildFoo()
和 getInstance()
。一切都是为了编写自我记录的代码。
@BalusC:谢谢你的解释,我试图比较静态工厂方法和构造函数,看看为什么本书推荐静态工厂方法。
你提到了diamond syntax
,它是什么以及它是如何工作的?
Foo<Map<Key,Value>> foo = new Foo<>();
【参考方案2】:
如果您知道要创建的类的具体类型,那么调用构造函数就可以了。
当您不完全确定如何构造所需的对象时,静态工厂方法非常有用。
工厂方法仍然在具体类型上调用构造函数,但该方法处理决定要实例化哪种具体类。然后,工厂方法返回一个接口类型(而不是具体类型),以便对调用者隐藏具体类型。
【讨论】:
工厂方法的一个有用方面是,在许多情况下,工厂方法的未来版本可以返回其他类型,而无需更改底层代码。例如,ImmutableMatrixOfDouble.Create
方法可能会查看它的参数是否是对角线上仅有非零元素的方阵,并在这种情况下返回ImmutableDiagonalMatrix
()。 256x256 ImmutableDiagonalMatrix
只需要大约 256x256 数组的 1/256 空间,因此如果许多不可变数组恰好适合该模式,则可以节省空间。【参考方案3】:
缺点 2.
用于创建对象的静态方法与任何其他静态函数具有相同的功能布局和外观。
仅通过查看创建对象的静态方法,您不会知道它会这样做,而相反的是相关部分。当您编写自己不熟悉的代码时,可能很难确定用于创建对象的正确静态方法。
Static Factory Pattern 的使用有据可查,非常有用,尤其是在Singleton 和Multiton 的情况下。在复杂对象的初始化中也很有用。
【讨论】:
以上是关于对象的创建:构造函数或静态工厂方法的主要内容,如果未能解决你的问题,请参考以下文章