关于Java:设计模式:工厂VS工厂方法与抽象工厂

Design Patterns: Factory vs Factory method vs Abstract Factory

我在看一个网站上的设计模式

在那里我读到了工厂、工厂方法和抽象工厂,但是它们太混乱了,对定义不清楚。根据定义

Factory - Creates objects without exposing the instantiation logic to the client and Refers to the newly created object through a common interface. Is a simplified version of Factory Method

Factory Method - Defines an interface for creating objects, but let subclasses to decide which class to instantiate and Refers to the newly created object through a common interface.

Abstract Factory - Offers the interface for creating a family of related objects, without explicitly specifying their classes.

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

有人能告诉我吗

  • 这三种模式有什么不同?
  • 何时使用哪个?
  • 如果可能的话,还有与这些模式相关的Java实例吗?

  • 这三种工厂类型都做同样的事情:它们是一个"智能构造函数"。

    假设你想创造两种水果:苹果和橘子。

    工厂

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class FruitFactory {

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

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

    }

    用例:构建一个苹果或一个橙色有点太复杂,在构造函数中都无法处理。

    工厂法

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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()中的公共功能:

    1
    2
    3
    4
    5
    6
    7
    class OrangePicker extends FruitPicker {

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

    抽象工厂

    抽象工厂通常用于依赖项注入/策略之类的事情,当您希望能够创建一个需要"相同类型"并且具有一些公共基类的整个对象系列时。这是一个与水果有关的模糊例子。这里的用例是我们要确保不会意外地在苹果上使用橘子采摘器。只要我们能从同一家工厂拿到水果和采摘机,它们就会相配。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    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();
      }
    }


  • How are these three patterns different from each other?
  • 工厂:创建对象而不向客户机公开实例化逻辑。

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

    抽象工厂:提供一个接口,用于创建相关或依赖对象的族,而不指定它们的具体类。

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

  • When to use which?
  • 工厂:客户机只需要一个类,而不关心它得到的具体实现是什么。

    工厂方法:客户机不知道在运行时需要创建什么具体的类,但只想得到一个可以完成这项工作的类。

    AbstractFactory:当您的系统必须创建多个产品系列,或者您希望在不公开实现细节的情况下提供产品库时。

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

  • And also if possible, any java examples related to these patterns?
  • 工厂和工厂法

    意图:

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

    UML图:

    enter image description here

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

    具体产品:实现产品接口

    创建者:声明工厂方法

    ConcreteCreator:实现工厂方法以返回ConcreteProduct的实例

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

    代码片段:

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

    与其他创造模式的比较:

  • 设计从使用工厂方法开始(不那么复杂,更可定制,子类激增),并随着设计者发现哪里需要更多的灵活性而向抽象工厂、原型或构建器(更灵活,更复杂)发展。

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

  • 进一步阅读参考:源代码设计模式


    工厂-分离工厂类以创建复杂对象。

    例如:创建水果对象的水果工厂类

    1
    2
    3
    4
    5
    class FruitFactory{

    public static Fruit getFruit(){...}

    }

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

    前任:

    1
    Calendar.getInstance() (Java's Calendar)

    抽象工厂法-工厂工厂

    比如说,我们想为电脑零件建造工厂。所以有几种类型的电脑,如笔记本电脑,台式机,服务器。

    所以对于每种类型的压缩机,我们都需要工厂。所以我们创建了一个像下面这样的高水平工厂

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

    现在这三个工厂又变成了工厂。(您将处理PartFactory本身,但在这个框架下,将根据您在抽象工厂中提供的内容进行单独的实现)

    1
    2
    3
    4
    5
      Interface-> PartFactory. getComputerPart(String s),
    Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

    Usage:
    new ComputerTypeAbstractFactory().getFactory("Laptop").getComputerPart("RAM")

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


    每一种设计模式都会蓬勃发展,以确保不会接触到编写的、工作的代码。我们都知道,一旦接触到工作代码,现有的工作流程中就存在缺陷,需要进行更多的测试来确保我们没有破坏任何东西。

    工厂模式基于输入条件创建对象,从而确保您不需要像这样编写代码,然后创建类似于此的对象,而不是类似于此的对象。旅游网站就是一个很好的例子。旅游网站只能提供旅游(航班、火车、巴士)或/和酒店或/和旅游景点套餐。现在,当用户选择下一个时,网站需要决定它需要创建什么对象。它也应该只创建旅游或酒店对象。

    现在,如果你设想在你的投资组合中添加另一个网站,并且你相信同样的核心被使用,例如,一个拼车网站,它现在搜索出租车并在线支付,你可以在你的核心使用一个抽象工厂。这样你就可以多开一家出租车和拼车厂了。

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

    希望现在一切都清楚了。再次研究这个网站,记住这个例子,希望它会有所帮助。我真的希望我已经正确地表示了模式:)。


    1
    2
    3
    4
    5
    6
    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
    }

    使用工厂方法,用户可以创建AbstractProductA的A1或A2。

    1
    2
    3
    4
    interface AbstractFactory {
        AbstractProductA getProductA(); //Factory Method
        AbstractProductB getProductB(); //Factory Method
    }

    但是抽象工厂有一个以上的工厂方法(例如:2个工厂方法),使用这些工厂方法,它将创建一组对象/相关对象。使用抽象工厂,用户可以创建abstractProductA、abstractProductB的a1、b1对象