【问题标题】:Simple factory VS Factory Method (why use factory method at all)简单工厂 VS 工厂方法(为什么要使用工厂方法)
【发布时间】:2021-04-01 20:59:01
【问题描述】:

我正在尝试学习模式并进入工厂,我了解简单工厂和工厂方法的概念,我知道它们是如何工作的,但我无法理解工厂方法相对于简单工厂有什么好处。示例:

//We have our clients here
public class Animal {}
public class Dog extends Animal{}
public class Cat extends Animal{}

在一个简单的工厂里我们会有这个东西:

public Animal getAnimal(String type) {
    switch (type) {
    case "cat": 
      return new Cat;
    case "dog":
      return new Dog;
    }
    return null;
}

现在我们使用工厂方法:

public abstract class AnimalFactory {
   public Animal createAnimal() {
       Animal animal = getAnimal();
       animal.pet();
       return animal;
   }
  
   protected abstract Animal getAnimal();

}
public class DogFactory extends AnimalFactory{
   public Animal getAnimal(){
      //some logic
      return new Dog;
   }
}
public class CatFactory extends AnimalFactory{
   public Animal getAnimal(){
      //some logic
      return new Cat;
   }
}

所以有趣的部分来了,对于工厂方法,我们需要使用多态,但我们仍然需要根据我们需要的类型来实例化,所以我想我们会有这样的东西:

public Animal getAnimal(String type) {
    AnimalFactory animalFactory;
    switch (type) {
    case "cat": 
      animalFactory = new CatFactory();  //polymorphism     
      return animalFactory.getAnimal();
    case "dog":
       animalFactory = new DogFactory();  //polymorphism     
      return animalFactory.getAnimal();
    }
    return null;
}

据我所知,设计模式的主要思想是让代码更可重用和更容易扩展,所以想象一下我们需要添加一种新动物,比如鹦鹉。在这两种情况下,我们都创建了扩展 Animal 类的 Parrot 类,在这两种情况下,我们都必须进入该 switch 语句并添加一个新案例“Parrot” 对于简单工厂,我们将直接实例化新 Parrot,对于工厂方法我们将实例化 ParrotFactory。 我的问题是有什么区别,为什么我们需要工厂方法模式?

我能看到的唯一好处是,在工厂方法中,您可以为将扩展它的工厂定义通用逻辑(是这样吗?)

【问题讨论】:

  • 这里的“工厂方法”示例不是任何类型的工厂。请参阅我的答案区分Factory Method from Abstract Factory。该线程中的前几个答案都包含有关工厂模式的良好信息。
  • 为什么我的例子不是工厂?工厂方法和工厂抽象之间的区别是另外一回事,我的问题是工厂方法比简单工厂有什么好处
  • 对 AnimalFactory 抽象类进行了编辑,这是缺少的吗?

标签: java design-patterns


【解决方案1】:

与大多数其他工厂模式相比,GoF 工厂方法模式的一个关键区别在于客户端的身份。在大多数工厂模式中,客户端是工厂的调用者

class Client {
    Product p = someFactoryObject.method();
}

但在工厂方法模式中,客户端(具体的)工厂。

class Client extends Factory {
    @Override
    Product factoryMethod() {
        return new ConcreteProduct();
    }
}

思考为什么这种工厂子类关系有意义的最简单方法是将父 Factory 想象为框架的一部分。该框架必须与任何Product 实现兼容,并且它希望每个客户定义自己的具体产品。在编写框架时,这些具体产品可能并不存在。

Client 将自己插入框架(通过继承)时,它定义了一个ConcreteProduct 供框架使用。与以前的答案相比,这与封装创造的复杂性无关。事实上,工厂方法的实现是一行行代码。

目的是,

工厂方法允许类将实例化推迟到子类。 (第 107 页)

延迟是关键。工厂方法允许您根据 未知 产品实现 API。继承是它用来做到这一点的工具。简单工厂(后来)在 Head First Design 中作为教学辅助工具发布,并非真正用于生产代码。

混淆源于工厂方法必须参数化的假设。这个假设得出的结论是,工厂的目的是允许客户在运行时在多个产品实现中进行选择。注意这里的factoryMethod() 没有参数。

要理解工厂方法模式,请考虑只有一个具体产品的场景,它在定义工厂方法 API 时根本不存在,并且不归 API 的作者所有。

【讨论】:

    【解决方案2】:

    工厂方法的好处通常是包含您不想混淆代码或不想从头开始创建的复杂类(或您需要的类层次结构)的逻辑,如果它们经常被使用。例如。汽车发动机。因此,您将凌乱的代码提取到工厂中,以使类层次结构更易于访问/更可重用,并通过隐藏复杂的细节使其余代码更具可读性。

    【讨论】:

    • 这个答案描述了简单工厂的好处。工厂方法模式是另一回事。
    【解决方案3】:

    好处是它封装了例如创建狗的逻辑。任何关于创建狗的修改只发生在 DogFactory(单一职责)上。当您要对对象进行任何设置时,这是一个不错的选择,例如在返回 dog 对象之前有任何代码。如果您在简单的工厂中执行此操作,则会搞砸并使该方法更长。但是因为在你的例子中它只做一个简单的new Dog()new Cat() 我更喜欢简单的工厂。恕我直言

    【讨论】:

    • 这与 Rob Evans 之前给出的答案基本相同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多