设计模式:工厂与工厂方法与抽象工厂

时间:2012-10-23 11:16:36

标签: java design-patterns language-agnostic factory factory-method

我正在从网站上阅读设计模式

在那里我读到了有关工厂,工厂方法和抽象工厂的信息,但它们很混乱,对定义并不清楚。根据定义

  

Factory - 创建对象而不将实例化逻辑暴露给客户端,并通过公共接口引用新创建的对象。 是Factory Method的简化版

     

工厂方法 - 定义用于创建对象的接口,但让子类决定实例化哪个类,并通过公共接口引用新创建的对象。

     

Abstract Factory - 提供用于创建相关对象族的界面,而无需明确指定其类。

我还查看了关于抽象工厂与工厂方法的其他stackoverflow线程,但是那里绘制的UML图使我的理解更加糟糕。

任何人都可以告诉我

  1. 这三种模式如何相互不同?
  2. 何时使用哪个?
  3. 如果可能的话,还有与这些模式相关的任何java示例?

8 个答案:

答案 0 :(得分:202)

所有三种工厂类型都做同样的事情:它们是“智能构造函数”。

假设您希望能够创建两种水果:Apple和Orange。

工厂

工厂是“固定的”,因为你只有一个没有子类化的实现。在这种情况下,您将拥有这样的类:

class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

使用案例:在构造函数中构造Apple或Orange有点太复杂了。

工厂方法

当您在类中进行一些通用处理时,通常会使用工厂方法,但想要改变实际使用的水果种类。所以:

abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

...然后您可以通过在子类中实现工厂方法来重用FruitPicker.pickFruit()中的常用功能:

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

抽象工厂

抽象工厂通常用于依赖注入/策略之类的东西,当你希望能够创建一个需要“同类”的整个对象系列,并且有一些共同的基类时。这是一个与水果有关的模糊例子。这里的用例是我们要确保我们不会在Apple上意外使用OrangePicker。只要我们从同一家工厂获得我们的水果和采摘器,他们就会匹配。

interface PlantFactory {

  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}

答案 1 :(得分:20)

  
      
  1. 这三种模式如何相互不同?
  2.   

工厂:创建对象而不将实例化逻辑暴露给客户端。

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

抽象工厂:提供用于创建相关或从属对象族的接口,而无需指定其具体类。

AbstractFactory 模式使用组合将创建对象的责任委托给另一个类,而工厂方法设计模式使用继承并依赖派生类或子类来创建对象

  
      
  1. 何时使用哪个?
  2.   

工厂:客户只需要一个类,而不关心它正在实现哪个具体实现。

工厂方法:客户端不知道在运行时需要创建哪些具体类,但只是想获得一个能够完成工作的类。

AbstactFactory:当您的系统必须创建多个产品系列,或者您希望提供产品库而不暴露实施细节时。

抽象工厂类通常使用Factory Method实现。工厂方法通常在模板方法中调用。

  
      
  1. 如果可能,还有与这些模式相关的任何java示例吗?
  2.   

工厂和工厂方法

<强> 意图:

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

UML diagram

enter image description here

产品:它定义了Factory方法创建的对象的接口。

ConcreteProduct:实现产品界面

创建者:声明工厂方法

ConcreateCreator:实现Factory方法以返回ConcreteProduct的实例

问题陈述:使用工厂方法创建游戏工厂,工厂方法定义游戏界面。

代码段:

Factory Pattern. When to use factory methods?

与其他创作模式的比较:

  1. 设计从工厂方法(不太复杂,可自定义,子类扩散)开始,向抽象工厂,原型或构建器发展(更灵活,更复杂的)因为设计师发现需要更多灵活性的地方

  2. 抽象工厂类通常使用工厂方法实现,但也可以使用原型

    <实现/ LI>

    进一步阅读的参考资料:Sourcemaking design-patterns

答案 2 :(得分:16)

工厂 - 单独的Factory类以创建复杂对象。

Ex:FruitFactory类创建Fruit的对象

class FruitFactory{

public static Fruit getFruit(){...}

}

工厂方法 - 而不是工厂的整个单独的类,只需在该类中添加一个方法作为工厂。

例如:

Calendar.getInstance() (Java's Calendar)

抽象工厂方法 - 工厂工厂

Ex:假设我们想为计算机零件建造工厂。因此有几种类型的计算机,如笔记本电脑,台式机,服务器。

因此,对于每种计算机类型,我们需要工厂。因此,我们创建了一个高级工厂,如下所示

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

现在这3个本身又是工厂。 (您将处理PartFactory本身,但根据您在抽象工厂中提供的内容,将会有单独的实现)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

编辑:编辑以根据评论中的反对意见为抽象工厂提供精确的界面。

答案 3 :(得分:9)

每个设计模式都蓬勃发展,以帮助确保不会触及书面的工作代码。我们都知道,一旦我们接触到工作代码,现有的工作流程就会出现缺陷,需要做更多的测试才能确保我们不会破坏任何内容。

工厂模式根据输入条件创建对象,从而确保您不需要编写代码,就像这样创建此类对象,否则此类对象。一个很好的例子是旅游网站。旅游网站只能提供旅行(航班,火车,公共汽车)或/和提供酒店或/和提供旅游景点套餐。现在,当用户选择下一个时,网站需要决定需要创建哪些对象。它是否应该只创建旅行或酒店对象。

现在,如果您想要在您的投资组合中添加另一个网站,并且您认为使用相同的核心,例如拼车网站,现在搜索出租车并在线进行付款,您可以在您的网站上使用抽象工厂核心。这样你就可以再搭乘一个出租车和拼车工厂。

两个工厂都没有任何关系,所以它是一个很好的设计,可以让它们保持在不同的工厂。

希望现在很清楚。再次研究网站,记住这个例子,希望它会有所帮助。我真的希望我能正确地代表模式:)。

答案 4 :(得分:2)

对于这个答案,我指的是“四人帮”一书。

书中没有没有“工厂”,“简单工厂”或“虚拟工厂”的定义。 通常,当人们谈论“工厂”模式时,他们可能在谈论创建类的特定对象的东西(而不是“构建器”模式);他们可能会或不会引用“工厂方法”或“抽象工厂”模式。任何人都可以实现“工厂”,因为这不是一个正式术语(请记住,某些人\公司\社区可以拥有自己的词汇)。

本书包含“抽象工厂”和“工厂方法”的定义。

这是本书中的定义,并简要解释了为什么两者都如此令人困惑。我省略了代码示例,因为您可以在其他答案中找到它们:

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

抽象工厂(GOF):提供一个用于创建相关或相关对象族的接口,而无需指定其具体类。

混乱的源头:通常,人们可以将在“工厂方法”模式下使用的类称为“工厂”。根据定义,此类是抽象的。这就是为什么容易将此类称为“抽象工厂”的原因。但这仅仅是班级的名称。您不应将其与“抽象工厂”模式(类名!=模式名)混淆。 “抽象工厂”模式是不同的-它使用抽象类。它定义了一个接口(不一定是编程语言接口),用于创建一个较大的对象或彼此相关或必须以特定方式创建的对象的一部分。

答案 5 :(得分:0)

AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

使用Factory Method,用户可以创建AbstractProductA的A1或A2。

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

但抽象工厂有超过1种工厂方法(例如:2种工厂方法),使用这些工厂方法,它将创建一组对象/相关对象。 使用Abstract Factory,用户可以创建AbstractProductA的A1,B1对象,AbstractProductB

答案 6 :(得分:0)

没有人引用原始书Design Patterns: Elements of Reusable Object-Oriented Software,该书在“讨论创造模式”(重点是我的部分)的前两段中给出了答案:

  

有两种常用的方法可以根据系统创建的对象类别对其进行参数化。一种方法是子类创建对象的类。这对应于使用“工厂方法(107)”模式。这种方法的主要缺点是,它可能需要一个新的子类才能更改产品的类。这样的变化可以级联。例如,当产品创建者本身是通过工厂方法创建的时,那么您还必须覆盖其创建者。

     

参数化系统的另一种方法更多地取决于对象组成:定义一个对象,该对象负责了解产品对象的类别,并使其成为系统的参数。这是抽象工厂(87),构建器(97)和原型(117)模式的关键方面。这三者都涉及创建一个新的“工厂对象”,其职责是创建产品对象。抽象工厂具有多个类别的工厂对象生产对象。 Builder具有使用相对复杂的协议以增量方式构建复杂产品的工厂对象。原型具有通过复制原型对象来构建产品的工厂对象。在这种情况下,工厂对象和原型是相同的对象,因为原型负责返回产品。

答案 7 :(得分:0)

基于Design Patterns in C#, 2nd Edition by Vaskaran Sarcar书中的图片:

1。简单工厂模式

创建对象而不将实例化逻辑暴露给客户端。

One primary goals design Unix system was to create environment promoted efficient program 

enter image description here

2。工厂方法模式

定义用于创建对象的接口,但让子类确定要实例化的类。

SimpleFactory simpleFactory = new SimpleFactory();
IAnimal dog = simpleFactory.CreateDog(); // Create dog
IAnimal tiger = simpleFactory.CreateTiger(); // Create tiger

enter image description here

3。抽象工厂模式(工厂工厂)

Abstract Factory提供了用于创建相关对象系列的界面,而无需显式指定其类

AnimalFactory dogFactory = new DogFactory(); 
IAnimal dog = dogFactory.CreateAnimal(); // Create dog

AnimalFactory tigerFactory = new TigerFactory();
IAnimal tiger = tigerFactory.CreateAnimal(); // Create tiger

enter image description here