【问题标题】:Purpose of factory classes in JavaJava 中工厂类的用途
【发布时间】:2013-05-13 20:05:34
【问题描述】:

我已经使用 Java 很长时间了,但我从来没有发现,是什么让 factories 如此特别。有人可以向我解释一下吗?我有什么理由要实现自己的factory(如果可能的话)?

【问题讨论】:

标签: java design-patterns factory


【解决方案1】:

工厂模式非常适合解耦类。例如,假设有一个公共接口Animal,以及一些实现它的类。 Dog, Cat.

如果您不知道用户在运行时想要生成什么,那么您不能创建Dog 指针。它根本行不通!

您可以做的是将其移植到单独的类中,并在运行时将 discriminator 传递给工厂类。然后该类将返回该对象。例如:

public Animal getInstance(String discriminator)
{
    if(discriminator.equals("Dog")) {
         return new Dog();
    }
    // etc.
}

调用类简单地使用:

String type = "Dog";
Animal value = Factory.getInstance(type);

这使得代码具有极高的可读性,将决策逻辑与对值执行的逻辑分开,并通过一些通用接口将类解耦。总而言之,漂亮的图案!

【讨论】:

  • 将字符串作为“命令”字符串传递对我来说总是有点不透明,传递某种最终静态字段总是更好(通常是 int 类型,但它并不重要),所以如果你想知道有什么选择你就去工厂。然后自动完成是选项
  • 是的,我同意。这实际上是我采取的方法,或者我使用外部enum。我只是想举一个不需要任何字段的快速示例。
【解决方案2】:

IMO 工厂类的最大好处是配置和数据封装。 API 设计可能是此类类真正派上用场的最常见场景。

例如,通过向开发人员提供工厂类而不是直接访问,我有一种方法可以轻松防止有人弄乱我的 API 内部。通过工厂课程,我还可以控制您对我的基础架构的了解程度。如果我不想告诉你我如何在内部提供服务的一切,我会给你一个工厂类。

出于可靠性和统一设计目的,最关键的内部结构应该包含在工厂类中。

它们是一种确保随机出现的开发者不会:

  • 打破内部结构
  • 获得不需要的特权
  • 打破配置格式

【讨论】:

    【解决方案3】:

    另一个很好的例子如下。假设用户想要使用 somes 集合来执行操作(在这种情况下选择集合来创建倒排索引)。您可以创建如下界面:

    interface CollectionsFactory {
        <E> Set<E> newSet();
        <K, V> Map<K, V> newMap();
    }
    

    然后你可以创建一个以集合工厂为参数的类。

    public class ConcreteInvertedIndex implements InvertedIndex {
        private final Map<String, Set<Document>> index;
        private final Set<Document> emptyDocSet;    
        private final CollectionsFactory c;
    
        public ConcreteInvertedIndex(CollectionsFactory c){
            this.c = c;
            this.index = c.newMap();
            this.emptyDocSet = c.newSet();
        }
    
    //some methods
    }
    

    最后由用户决定他想使用哪些集合来执行这些操作:

    CollectionsFactory c = new CollectionsFactory() {
    
                @Override
                public <E> Set<E> newSet() {
                    return new HashSet<E>(); //or you can return a TreeSet per example
                }
    
                @Override
                public <K, V> Map<K, V> newMap() {
                    return new TreeMap<K, V>();//or you can return an HashMap per example
                }
            };
            InvertedIndex ii = new ConcreteInvertedIndex(c);
    

    【讨论】:

      【解决方案4】:

      在以下情况下使用工厂方法模式

      · 一个类无法预测它必须创建的对象类。

      · 一个类希望它的子类指定它创建的对象。

      · 类将责任委托给几个助手子类之一,并且 你想本地化哪个助手子类是委托的知识。

      【讨论】:

        【解决方案5】:

        JDK 中广泛使用工厂来支持 SPI(服务提供者接口)的概念 - 旨在由第三方实现或扩展的 API。例如。 DocumentBuilderFactory.newInstance() 使用复杂的 4 步搜索算法来查找实际实现。

        我认为开发应用程序而不是库的程序员应该在软件设计中支持“简单就是最好”的方法。

        【讨论】:

          【解决方案6】:

          您可以将它们与私有构造函数结合使用来创建单例。它确保 bean(可能是服务)不能被创建为非单例。

          你也可以通过将构造函数设为私有来禁止创建类,这样你就可以在工厂方法中添加一些逻辑,没有人可以绕过它。

          编辑:我知道有人会用带参数的“create”方法替换每个 bean 中的构造函数(以便集中 bean 填充逻辑),但我不是一个忠实的粉丝这种方法。

          【讨论】:

          • 我不认为这个问题是关于静态工厂的。
          • 从问题中看不清楚,但你说得对,我只回答了部分......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-01
          • 1970-01-01
          相关资源
          最近更新 更多