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

Jus*_*per 164 java language-agnostic design-patterns factory factory-method

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

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

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

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

抽象工厂 - 提供用于创建相关对象族的界面,而无需明确指定其类.

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

有谁能告诉我

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

And*_*sen 219

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

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

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

class FruitFactory {

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

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

}
Run Code Online (Sandbox Code Playgroud)

使用案例:构造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>
  }
}
Run Code Online (Sandbox Code Playgroud)

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

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}
Run Code Online (Sandbox Code Playgroud)

抽象工厂

抽象工厂通常用于依赖注入/策略之类的东西,当你想要能够创建一整套需要"同类"的对象时,并且有一些共同的基类.这是一个与水果有关的模糊例子.这里的用例是我们要确保我们不会在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();
  }
}
Run Code Online (Sandbox Code Playgroud)

  • +1这是我对这些模式的理解最相似的答案.添加调用代码(客户端)的示例也会有所帮助吗?困扰我的问题是:我们可以说抽象工厂模式只是工厂扩展了工厂方法模式(如果这是真的,我对这个主题很清楚)? (8认同)
  • 这是我花了数年时间寻找的例子. (7认同)
  • @AndréAndrade 如何调用 **工厂方法** ?请提供一个小代码示例:) 这将消除我对其用法的疑问 (2认同)

Rav*_*abu 22

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

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

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

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

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

  1. 什么时候用哪个?

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

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

AbstactFactory: 当您的系统必须创建多个系列的产品或您想要提供产品库而不暴露实现细节时.

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

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

工厂和工厂方法

意图:

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

UML图:

在此输入图像描述

Product:它定义Factory方法创建的对象的接口.

ConcreteProduct:实现产品界面

创建者:声明工厂方法

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

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

代码段:

工厂模式.何时使用工厂方法?

与其他创作模式比较:

  1. 设计从使用工厂方法开始(不那么复杂,可定制,子类增加)并向Abstract Factory,Prototype或Builder发展(更灵活,更复杂),因为设计师发现需要更多灵活性的地方

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

进一步阅读的参考资料:源代码设计模式


Rav*_*i K 17

Factory - 用于创建复杂对象的Separate Factory类.

例:FruitFactory类创建Fruit的对象

class FruitFactory{

public static Fruit getFruit(){...}

}
Run Code Online (Sandbox Code Playgroud)

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

例如:

Calendar.getInstance() (Java's Calendar)
Run Code Online (Sandbox Code Playgroud)

抽象工厂方法 - 工厂工厂

例如:让我们说我们想建立电脑零件工厂.因此有几种类型的计算机,如笔记本电脑,台式机,服务器.

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

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

现在这3个本身又是工厂.(您将处理PartFactory本身,但在引擎盖下,将根据您在抽象工厂中提供的内容进行单独实现)

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

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)
Run Code Online (Sandbox Code Playgroud)

编辑:根据评论中的异议编辑,为抽象工厂提供精确的界面.

  • 我已更新答案以解决您的问题。实际上抽象工厂只不过是工厂的工厂而已。我之前给出的例子仅供参考(假设读者在实际实现时会照顾接口)。还是谢谢通知。改进总是好的。:) (2认同)

Sid*_*rth 10

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

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

现在,如果您想要在您的投资组合中添加另一个网站,并且您认为使用相同的核心,例如拼车网站,现在搜索出租车并在线进行付款,您可以在您的核心使用抽象工厂.通过这种方式,您可以在另外一个出租车和拼车车间工作.

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

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


Pav*_*hin 10

对于这个答案,我参考了“四人帮”一书。

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

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

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

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

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

混乱的根源:通常,人们可以将“工厂方法”模式中使用的类称为“工厂”。这个类根据定义是抽象的。这就是为什么可以轻松地将此类称为“抽象工厂”的原因。但这只是类的名称;您不应该将它与“抽象工厂”模式(类名!= 模式名)混淆。在“抽象工厂”模式不同-它并没有使用抽象类; 它定义了一个接口(不一定是编程语言接口),用于创建一个或多个彼此相关或必须以特定方式创建的更大对象的部分。


Ham*_*aei 5

根据Vaskaran Sarcar 的Design Patterns in C#, 2nd Edition》中的图片

1. 简单工厂模式

在不向客户端公开实例化逻辑的情况下创建对象。

SimpleFactory simpleFactory = new SimpleFactory();
IAnimal dog = simpleFactory.CreateDog(); // Create dog
IAnimal tiger = simpleFactory.CreateTiger(); // Create tiger
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

2. 工厂​​方法模式

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

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

AnimalFactory tigerFactory = new TigerFactory();
IAnimal tiger = tigerFactory.CreateAnimal(); // Create tiger
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

3.抽象工厂模式(factory of factory)

抽象工厂提供了用于创建相关对象系列的接口,而无需明确指定它们的类

IAnimalFactory petAnimalFactory = FactoryProvider.GetAnimalFactory("pet");
IDog dog = petAnimalFactory.GetDog(); // Create pet dog
ITiger tiger = petAnimalFactory.GetTiger();  // Create pet tiger

IAnimalFactory wildAnimalFactory = FactoryProvider.GetAnimalFactory("wild");
IDog dog = wildAnimalFactory .GetDog(); // Create wild dog
ITiger tiger = wildAnimalFactory .GetTiger();  // Create wild tiger
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 100% 清晰度。被低估的答案 (10认同)