考虑提供静态工厂方法而不是构造函数

时间:2012-10-24 09:58:08

标签: java

允许客户端获取实例的类的常规方法是提供公共构造函数。另一种方法是提供一个公共静态工厂方法,它只是一个返回类实例的静态方法。使用静态工厂方法有什么利弊?

5 个答案:

答案 0 :(得分:9)

“有效Java”一书的这一章很好地解释了它:Consider Static Factory instead of Constructors。它以你能理解的最佳方式解释了它们的所有优点和缺点。

引用本书的优点和缺点:

<强>优点

  • 静态工厂方法的一个优点是,与构造函数不同,它们具有名称。
  • 静态工厂方法的第二个优点是,与构造函数不同,它们不需要在每次调用时都创建新对象。
  • 静态工厂方法的第三个优点是,与构造函数不同,它们可以返回其返回类型的任何子类型的对象。
  • 静态工厂方法的第四个优点是它们减少了创建参数化类型实例的详细程度(在Java 7中可以忽略这一点)

<强>缺点

  • 仅提供静态工厂方法的主要缺点是没有公共或受保护构造函数的类不能被子类化

  • 静态工厂方法的第二个缺点是它们不容易与其他静态方法区分开来。

您可以在我提供的链接中更详细地研究它们。

答案 1 :(得分:2)

唯一的问题是编写更多的代码,但它仍然存在,因此您至少需要一些工厂的好处。

工厂不需要总是返回一个新对象,这是一个优点。

Factory可以实例化它想要的任何子类,那是另一个。

在我的项目中,我经常添加工厂只是为了让我的客户端代码看起来更好。如果对工厂方法使用静态导入,则调用看起来比new表达式更好,特别是如果类的名称不是特别简洁,通常就是这种情况。

答案 2 :(得分:1)

优势: - 静态工厂方法的一个优点是,与构造函数不同,它们具有名称。 - 静态工厂方法的第二个优点是,与构造函数不同,每次调用它们时都不需要创建新对象。 - 它们可以返回其返回类型的任何子类型的对象。 Disavantage: - 静态工厂方法的主要缺点是没有公共或受保护构造函数的类不能被子类化。 - 它们不容易与其他静态方法区分开来。

答案 3 :(得分:0)

我会对问题的原始作者说静态工厂方法是一种工具。像所有工具一样,它们具有最适合的用途,可以通过的其他用途,以及其适应性差的其他用途。举一个现实世界的例子,锤子很适合驱动钉子,足以顶住带有钉子去除端的密封箱子(撬棍仍然会好得多),但是对于刨平粗糙表面是无用的。

工厂方法指的是一组创建设计模式之一,即用于创建对象的范例。在诸如“Builder”和“Prototype”之类的一些创作设计模式中,不仅不鼓励使用新的运算符来创建对象,它被认为对整体设计目标有害。人们谈论的创造性设计模式是......

  1. 工厂方法
  2. 抽象工厂方法
  3. 单身人士模式
  4. 生成器
  5. 原型
  6. 一般来说,工厂方法用于根据用户或设计者提供给方法的数据从一组相关的子类创建对象。但更具体地说,即使返回的对象每次都相同,静态工厂方法也可以控制对象的创建。例如,当创建对象的过程在时间和资源方面非常昂贵时,这可能是非常重要的。在这种情况下,使用新的运算符来创建对象可能会导致严重的性能损失。

    一种解决方案可能是维护可重用的对象池。通过使用静态工厂方法,应用程序设计人员可以提供逻辑以返回可用的现有对象(如果有)。这样可以节省构建新对象的潜在高成本。这正是由提供“连接池”的连接管理器对网络数据库连接所做的。客户端每次发出请求时都不会构建新的数据库连接,而是从现有对象池中分配连接对象(如果有的话)。这是一个使用新运算符实际上会对应用程序性能有害并且会破坏软件工程师设计目标的情况的示例。

    考虑使用工厂方法创建对象而不是新运算符的好时机是:

    • 将要创建的对象属于可根据提供的数据创建的几个可能的对象子类之一。
    • 有一个很好的理由可以控制对象创建过程,而不是构造函数,例如。 Singleton设计模式需要静态工厂方法。

    考虑使用工厂方法的好时机是:

    • 简单轻巧的物品

    所有这些都是关于枚举软件设计问题,然后决定哪些工具最适合解决它。静态工厂方法对于某些事情是好的,对其他人来说不太好......就像任何工具一样。

答案 4 :(得分:0)

其中一个优点是您可以为工厂方法提供可理解的名称。它将帮助您轻松了解函数的功能,并在将来轻松维护代码。看看这个例子,希望它能帮到你。

    public class Contact {

    private Contact(String displayName, String phoneNumber, int contactType){
    //do something
    }

    //then we will have few functon static to get constructor private
    public static createContactUnknow(String phoneNumber){
        return new Contact("","00000000",0);
    }

    public static createContactValid(String displayName, String phoneNumber, int contactType){
        return new Contact(displayName, phoneNumber, contactType);
    }
}

    //then
    Contact myGirlFriend = Contact.createContactValid("xxxx","000000",1);
    Contact unknowFriend = Contact.createContactUnknow("45454545");