【问题标题】:instance factory methods Vs Static factory methods实例工厂方法与静态工厂方法
【发布时间】:2011-11-16 05:32:44
【问题描述】:

不能所有的工厂方法都是静态的吗?生产产品的东西是否需要状态?什么时候适合使用实例工厂或静态工厂方法?你能提供区分这两者的例子吗?

【问题讨论】:

  • “一个实例静态方法”是自相矛盾的。请修改您的问题。也许您的意思是“实例工厂方法”。至于您的具体问题,您基本上是在询问“抽象工厂”与“工厂方法”。那必须给你新的关键词。例如,维基百科有 2 篇关于这些设计模式的独立文章。
  • 静态工厂方法本质上是命名构造函数,所以是的,它们必须是静态的。我不熟悉实例工厂方法,除非您指的是具有工厂实例方法的抽象工厂模式,但这是一个不同的概念。恕我直言,静态工厂方法是一个不好的名字,会引起混淆,它应该被命名为命名构造方法,清楚地表明它是使用默认 Java 构造函数语法的更强大的替代方案。

标签: java factory-pattern


【解决方案1】:

假设“实例工厂方法”实际上是指 GoF 的“工厂方法”,Joshua Bloch 在他的“Effective Java”一书中描述了术语“静态工厂方法”。谷歌搜索我到达了这些网站:

希望它有助于使差异更加清晰。

听从 Marvo 的建议:

  • GoF 中所述的工厂方法:

    定义一个用于创建对象的接口,但让子类决定实例化哪个类。工厂方法允许类将实例化推迟到子类。

示例(Java 代码):

    public abstract class Product { ... }

    public class ConcreteProduct extends Product { ... }

    public abstract class Creator {
      public void anOperation() { ... product = factoryMethod(); ... }
      public abstract Product factoryMethod();
    }

    public class ConcreteCreator extends Creator {
      public Product factoryMethod() { return new ConcreteProduct(); }
    }
  • Effective Java 中所述的静态工厂方法:

    一个类可以提供一个公共静态工厂方法,它只是一个返回类实例的静态方法。 (...) 静态工厂方法的一个优点是,与构造函数不同,它们有名称。 (...) 静态工厂方法的第二个优点是,与构造函数不同,它们不需要在每次调用时都创建一个新对象。 (...) 静态工厂方法的第三个优点是,与构造函数不同,它们可以返回其返回类型的任何子类型的对象。 (...) 只提供静态工厂方法的主要缺点是没有公共或受保护构造函数的类不能被子类化。

示例(Java 代码):

    public class Boolean {
      ...
      public static Boolean valueOf(boolean b) {
        return b ? Boolean.TRUE : Boolean.FALSE;
      }
      ...
    }

【讨论】:

  • @user2434,你可以接受这个答案吗?
【解决方案2】:

我目前的偏好是使工厂方法不是静态的,以便于测试。您不能在运行时更改静态工厂方法调用,而如果我可以为对象提供工厂实现,那么我可以更彻底地测试它,因为我可以更好地控制上下文和对象图。

【讨论】:

  • 我不明白你在说什么。你能举个例子来说明你的观点吗?
  • @user2434:这现在取决于我们所说的静态工厂与实例工厂的确切含义。你能提供一个你认为静态工厂和实例工厂是什么样子的例子吗?
  • @NateW。我说的“你不能在运行时更改静态工厂方法调用”不是你的意思,可以更详细地解释它
  • 什么@NateW。意思是,如果我有一个调用静态工厂方法的方法,我将与该静态工厂方法的返回紧密耦合。如果我使用非静态工厂,我可以在测试期间传入模拟工厂以返回模拟对象。 ``` 工厂工厂 = Mockito.mock(Factory.class);具体具体 = Mockito.mock(Concrete.class); when(factory.create()).thenReturn(concrete); ClassToTest.methodToTest(工厂); // 使用工厂创建 Concrete 的实例 ```
【解决方案3】:

如果你从你的工厂返回一个单例,那么你将需要确保你只有一个实例,如果你每次调用工厂时都要创建一个新实例,那么将它设为静态。

【讨论】:

  • 为什么不一直使用静态工厂来返回新实例呢?不可能吗?
  • 这完全没有问题,我通常是这样做的。
【解决方案4】:

这取决于,例如,您可以拥有一个只生产一定数量的对象的工厂,在这种情况下会有一个关联的状态。大多数情况下,工厂方法可以是静态的,只要它们不依赖任何非静态变量(例如非静态全局变量等)来创建它们。它还倾向于为应用程序的不同部分区分不同的工厂,因此取决于您的工厂中是否存在状态,这并不是所有工厂方法都应该是静态的,请检查适用于哪种情况你并适当地写它。

另一个考虑因素是 static 关键字,这会导致静态的东西只在内存中实例化一次,但缺点是它总是驻留在进程内存中(这会增加工作集的大小)。这可能是您不想要的,因为您的工厂在某些区域可能具有非常高的位置,否则它只会在其他地方耗尽内存,但这通常是一个优化问题,只有在内存问题时才应该考虑您的应用程序中会出现压力。

【讨论】:

    【解决方案5】:

    如果之前需要实例,那么您可以使用静态工厂,否则实例化工厂本身并将其传递给您的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多