【问题标题】:When to use the abstract factory pattern?什么时候使用抽象工厂模式?
【发布时间】:2011-05-18 21:18:43
【问题描述】:

我试图简明扼要地描述何时为我自己和我的团队使用工厂。我遇到了以下相关问题,这在一定程度上有所帮助:

根据这些链接和一堆其他来源(列在底部),我想出了以下内容:

何时使用抽象工厂模式:

  • 当您使用接口 var 或“新”运算符时
    • 例如用户用户 = 新的 ConcreteUserImpl();
  • 并且您正在编写的代码在某些时候应该是可测试/可扩展的

说明:

  • 接口本质上意味着多种实现(有利于单元测试)
  • 接口变量暗示符合 OCP 和 LSP 的代码(支持子类化)
  • 使用“new”运算符会破坏 OCP/DI,因为高度耦合的类很难测试或更改

“我是否为每种对象类型都创建了一个工厂?这似乎太过分了。”

  • 不,您可以拥有一个(或几个)工厂来生产很多(通常是相关的)对象类型
  • 例如appFactory.createUser(); appFactory.createCatalog();等等。

何时不使用工厂:

  • 新对象非常简单,不太可能被子分类
    • 例如List list = new ArrayList();
  • 新对象没有兴趣测试
    • 没有依赖关系
    • 不执行任何相关或长期运行的工作
    • 例如记录器 log = new SimpleLogger();

参考资料:


我的问题是:我的总结是否准确,是否有意义?有什么我忽略的吗?

提前致谢。

【问题讨论】:

  • 我讨厌恢复旧线程,但是...我不同意记录器应该像上面那样是新的。我经常在不同的测试环境中运行不同的记录器。我将环境配置为使用特定的记录器并将其注入到记录的对象中。 (我什至可以注入记录器数组。)

标签: oop design-patterns language-agnostic factory factory-pattern


【解决方案1】:

我还要说,当您有想要的特定实现时,不要使用工厂。继续List 示例,我知道我想要一个ArrayList,因为我正在进行随机访问。当我可以自己做时,我不想依赖工厂来做这件事。

相反,当我不想知道具体的子类时,我可以使用工厂并让它担心实际实例化哪个对象。

我想我建议您在“何时使用抽象工厂模式”中添加一个项目符号,说明“并且您并不真正关心您获得哪个具体子类”,反之则为“何时不使用使用工厂”。

编辑:小心避免general-purpose tool-building factory factory factory

【讨论】:

  • 好吧 - 假设我想要缓存线程池的具体优势: ExecutorService pool = Executors.newCachedThreadPool();但是,在我的单元测试中(无论出于何种原因),我对池中完成的工作的结果不感兴趣,并且我不想每次运行测试时都必须等待工作完成。那么我不会仍然使用工厂,以便我可以存根/模拟我的线程池进行测试吗?在我看来,当您考虑测试时,您希望将大部分代码视为不关心实际实现,以免编写无法测试的代码。
  • 是的,没错。通常,您的大部分代码都不关心实际的实现。在 ArrayListLinkedList 之间进行选择是您关心的少数几次之一,因为它们具有不同的性能特征。你是对的:为了测试,最好尽可能忽略实际的实现。
【解决方案2】:

一般来说,当您希望能够通过外部配置切换实现时使用它。

JDBC 和 JAXP 就是很好的例子。更多示例,请查看this answer

【讨论】:

  • 那不是意味着使用 IoC 容器吗?
  • 您能否详细说明何时使用自定义工厂与 IoC 来通过配置切换对象类型?
  • @Max:取决于 API 是否要在 IoC 容器上运行。
【解决方案3】:

抽象工厂模式提供了一种封装具体工厂的方法,这些工厂彼此共享一些共同点,这意味着它们实现相同的接口/抽象类。

当您想要控制对象的初始化时,您需要使用工厂模式,而不是将控制权交给消费者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多