在java中创建对象的最佳实践

时间:2011-10-14 18:08:17

标签: java object constructor javabeans factory

我正在阅读Joshua Bloch撰写的 Effective Java 一书。在第一章中,他说使用工厂而不是构造函数,并列出了这种方法的优缺点。据我所知,缺点与对象构造没有密切关系。

此外,Bloch说Java Bean的构造风格也有缺点。 资料来源:http://www.javapractices.com/topic/TopicAction.do?Id=84

好的,所以使用构造函数不是很好,Java bean不是很好,工厂很好,所以你可以做一些缓存查找并避免创建额外的对象(取决于具体情况,有时你不想要缓存)。

如果我试图避免构造函数和java bean,我应该如何创建一个对象?

我错过了一点吗?什么是最佳做法?

编辑:

class Foo{
   private Foo(){}

   public Foo Create(){
      return new Foo();
   }

}

8 个答案:

答案 0 :(得分:7)

使用构造函数直到你开始感受到Bloch提到的缺点。然后考虑工厂,依赖注入或其他方法是否更好。

答案 1 :(得分:2)

对具有少量参数的简单对象使用构造函数。如果参数的数量增加,那么就开始考虑bloch建议的构建器或工厂。

大多数简单案例,构造函数都能很好地完成工作。

我的经验是,如果定义对象的属性数量增长很多,我会回过头来检查设计并找出是否必须以更好的方式对属性进行分组。就像DININGTABLE可以分成n个腿+ 1个顶部木制部分。

如果对所有对象构造使用工厂模式,则看起来不太好。

  • 除非有充分的理由,否则永远不要在你的课程中使用类似setter的java bean *你会感谢我这样说,因为这将使代码的维护成为一场噩梦 - 你永远不会知道这些人是谁以及如何调用来改变对象的状态。应该通过构造函数尽可能多地构造对象,尽可能使它们成为不可变的,如果不是通过一种或两种方法只通过几种方式来更新对象的状态。

答案 2 :(得分:1)

这取决于场景。正如您所提到的,如果涉及缓存,那么静态工厂是更好的方式。如果有很多状态变量,那么使用Builder模式。

答案 3 :(得分:1)

您可能有兴趣熟悉Dependency Injection模式,Google Guice是最常用的实现框架之一。

答案 4 :(得分:1)

嗯,我认为这个家伙正在苦苦挣扎的是Inversion of Control模式:

http://en.wikipedia.org/wiki/Inversion_of_control

不要在这里做论文,我只是说在对象实例的这个狭窄的环境中反转控制是指与对象实例单独服务处理的事实(和好处),而不是必须实现那些手动对象。实现这一目标的一种方法是工厂模式,根据你的说法,这个人正在描述。另一个是使用一个为你做IOC的框架,比如Spring:

http://static.springsource.org/spring/docs/2.0.x/reference/beans.html

(实际上距离工厂模式不远)

第三个选项是制作您自己的IOC机制,以某种方式处理对象实例化,这样您就不必每次都明确地执行此操作。

这里的想法不是停止使用构造函数来创建实例,你总是使用它来获取实例,这里的想法是WHEN以及你如何调用该构造函数:

  • 你是否在需要实例的类中直接调用它
  • 您是否有一个单独的机制(如Factory)处理在需要时获取该实例(依赖项),这样您就不会自己明确地执行此操作

两种方式都有优势。通常情况下,单独处理instanciation更好,而不是手动执行,因为它会导致更清晰,耦合度更低,代码更易测试。

答案 5 :(得分:1)

如果你遇到一个正在做数学的程序来计算一周中哪一天到处都是,你会怎么想?您可能会认为“数学可以计算出它应该采用自己的方法中的哪一天,因此它可以只表达一次,只要代码需要知道哪一天,就可以调用该方法本周是“。

构建一个对象与确定一周中的哪一天完全不同。在一个地方做它,使它成为一个方法,并从需要新对象的任何地方调用该方法。

现在,在某些情况下,该方法本身可以是构造函数(构造函数实际上只是一种有趣的方法,对吧?)。在其他方法中,该方法将调用构造函数,该构造函数不会在其他任何地方使用。这取决于创建对象需要做多少工作,以及要隐藏要创建的对象的类的数量(想象一下createDaysOfTheWeek工厂方法 - 它可以返回Collection<DayOfTheWeek>,并隐藏它是ArrayListLinkedHashSetEnumSet或其他什么的事实。以工厂方法包装结构可以为您提供更多封装,但透明度更低。制作好的代码需要这两种品质,但是像啤酒和馅饼一样,你需要平衡它们。

答案 6 :(得分:0)

始终在上下文中判断建议。构造函数是创建对象的标准方法,但它们并非完全没有缺点。

例如,他谈到了一个服务提供者框架 - 这只能在构造对象的工厂方法上实现。但关键是你不要一直设计服务提供者框架。

再次,他引用了Collection框架中使用实例控制类的示例。如果将对象创建限制为简单构造函数样式,则无法执行此操作。但同样,日常代码不需要采用实例控制的类。

他支持工厂方法还有其他一些案例 - 所有这些都是在某些使用环境下进行的。在其他情况下,构造者可能就足够了。

答案 7 :(得分:0)

您可以使用Cinstructor创建对象,例如使用new,如下所示:

Foo f=new Foo();

有一个名为singleton的概念。在这种情况下,您可以使用上面显示的此类型,但是使create函数为静态,否则用户将如何调用函数create,如下所示:

class Foo{
   private Foo(){}

   public static Foo Create(){
      return new Foo();
   }

}