我们是否需要优先选择构造函数而不是静态工厂方法?如果是的话,何时?

时间:2012-03-09 15:03:18

标签: java design-patterns constructor factory-pattern effective-java

我一直在阅读 Joshua Bloch Effective Java ,到目前为止,它确实辜负了它的声誉。第一个项目为静态工厂方法而非构造函数提供了令人信服的理由。这么多,我开始质疑好老建筑师的有效性:)。

本书的优点/缺点概述如下:

  

优点:

     
      
  1. 他们有名字!
  2.   
  3. 我们有完整的实例控制(单身人士,表演等)
  4.   
  5. 他们可以返回子类型/接口
  6.   
  7. 编译器可以提供类型推断
  8.         

    缺点:

         
        
    1. 私有类不能被子类化
    2.   
    3. 他们在文档中并不像构造函数那样突出
    4.   

第一个缺点实际上可能是 A Good Thing (正如书中所提到的)。第二个,我认为只是一个小缺点,可以通过即将发布的java版本(javadoc的注释等)轻松解决。

看起来,最终工厂方法几乎具有构造函数的所有优点,有许多优点,并没有真正的缺点!

所以,我的问题基本上分为三个部分:

  1. 默认情况下,总是在构造函数上使用静态工厂方法是不错的做法?
  2. 使用构造函数是否合理?
  3. 为什么面向对象的语言不能为工厂提供语言级支持?
  4. 注意:有两个类似的问题:When to use a Constructor and when to use getInstance() method (static factory methods)?Creation of Objects: Constructors or Static Factory Methods。然而,答案要么只是提供上面的列表,要么重申我已经知道的静态工厂方法背后的基本原理。

4 个答案:

答案 0 :(得分:7)

静态工厂最后仍然需要调用构造函数。您可以将大部分功能移动到静态工厂中,但无法避免使用构造函数。

另一方面,对于简单的情况,你可以只拥有一个没有静态工厂的构造函数。

构造函数是设置最终字段的唯一方法,IMHO优于非最终字段。

您可以在子类中使用构造函数。您不能将静态工厂用于子类。

如果您有一个良好的依赖注入框架来构建组件的依赖关系,您可能会发现静态工厂不会添加太多。

答案 1 :(得分:3)

我喜欢你强调的一个类似问题的评论:

(关于如何决定是否应该在构造函数上使用工厂方法),

“你需要决定你要完成什么。要么你不希望别人打电话给你的构造函数(你正在创建一个单例或工厂),要么你不介意(如上面的NumberFormat) ,为了方便调用者,他们正在初始化一些对象)“

对我来说,这意味着 有理由使用构造函数,其中不需要工厂方法。它不需要工厂,只会使代码更难以遵循(“这里返回的确切的子类?”)

答案 2 :(得分:3)

我在这里与Josh Bloch达成了非常强烈的协议,他比我更好地表达了这个案例,但是这里有一些静态工厂不合适的地方:

  • 依赖注入更明智; DI系统(当然是Guice)倾向于通过他们的构造者注入东西。特别是,当您希望将来可能会更改构造函数的参数时,DI是合适的。
  • 当你特意打算让人们编写子类时,你正在为他们提供一个框架来实现。

答案 3 :(得分:0)

构造函数很无聊,你知道在哪里搜索它们,你知道它们的范围,它们在某种程度上是可预测的。他们在那里建造物体本身,而不是做上帝般的工作。如果你做了太多与构造对象无关的其他东西,你知道你做错了什么。并且仅通过重命名方法不可能“治愈”这个。因此,当您没有顶级的开发人员时,他们往往会更专注,更“优秀”的代码质量。 (如果你有后者,我提到的要点无关紧要。)

无聊的东西。让我们做一些更有趣,更具智慧的事情...

仅供记录:我不会忽视问题和其他答案中提到的要点,我只想补充这一点。