我知道有很多关于这两种模式之间差异的帖子,但有一些东西我找不到。

From what I have been reading, I see that the factory method pattern allows you to define how to create a single concrete product but hiding the implementation from the client as they will see a generic product. My first question is about the abstract factory. Is its role to allow you to create families of concrete objects in (that can depend on what specific factory you use) rather than just a single concrete object? Does the abstract factory only return one very large object or many objects depending on what methods you call?

我最后两个问题是关于一句我在很多地方都见过的引语,我不能完全理解:

两者之间的一个区别是 使用抽象工厂模式,a 类委托的责任 对象实例化到另一个对象 通过合成,而工厂 方法模式使用继承和 类依赖于子类来处理 所需的对象实例化。

我的理解是,工厂方法模式有一个Creator接口,它将使ConcreteCreator负责知道要实例化哪个ConcreteProduct。这就是使用继承来处理对象实例化的意思吗?

现在,关于引用,抽象工厂模式是如何通过组合将对象实例化的责任委托给另一个对象的?这是什么意思?在我看来,抽象工厂模式似乎也使用继承来完成构造过程,但我仍然在学习这些模式。

任何帮助,特别是最后一个问题,将非常感激。


当前回答

让我们明确一点,在生产代码中,大多数时候我们使用抽象工厂模式,因为类A是用接口b编程的,而A需要创建b的实例,因此A必须有一个工厂对象来生成b的实例,因此A不依赖于b的任何具体实例,希望它有帮助。

其他回答

我的第一个问题是关于抽象工厂。它的角色是否允许您在其中创建一系列具体对象(这取决于您使用的具体工厂),而不仅仅是单个具体对象?

是的。抽象工厂的目的是:

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


根据调用的方法,抽象工厂只返回一个非常大的对象还是多个对象?

理想情况下,它应该为客户端调用的每个方法返回一个对象。

我的理解是,工厂方法模式有一个Creator接口,它将使ConcreteCreator负责知道要实例化哪个ConcreteProduct。这就是使用继承来处理对象实例化的意思吗?

是的。工厂方法使用继承。

抽象工厂模式委托对象实例化的责任通过组合到另一个对象?这是什么意思?

AbstractFactory定义了一个FactoryMethod,而ConcreteFactory负责构建一个ConcreteProduct。只需按照本文中的代码示例进行操作。

你可以在SE的相关文章中找到更多细节:

工厂模式和抽象工厂模式之间的基本区别是什么?

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

为了便于理解,考虑这个例子。

电信公司提供什么?例如宽带,电话线和移动电话,你被要求创建一个应用程序,向他们的客户提供他们的产品。

一般来说,你在这里要做的是,通过你的工厂方法创建产品,即宽带,电话线和手机,在那里你知道你为这些产品拥有什么属性,这是非常简单的。

现在,该公司想要为他们的客户提供他们的产品捆绑,即宽带、电话线和移动设备,而抽象工厂就来了。

换句话说,抽象工厂是由其他工厂组成的,他们负责创造自己的产品,抽象工厂知道如何在自己的责任方面把这些产品放在更有意义的地方。

在这种情况下,BundleFactory是抽象工厂,BroadbandFactory, PhonelineFactory和MobileFactory是工厂。为了进一步简化,这些工厂将使用工厂方法初始化各个产品。

运行下面的代码示例:

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

希望这能有所帮助。

A)工厂方法模式

工厂方法是一种创建设计模式,它提供了创建对象的接口,但允许子类改变将要创建的对象的类型。

如果在基类和扩展它的子类中有一个创建方法,您可能会考虑工厂方法。

B)抽象工厂模式

抽象工厂是一种创造性的设计模式,允许在不指定具体类的情况下产生相关或依赖的对象族。

什么是“对象族”?例如,以这组类为例:传输+引擎+控制。这些可能有几种变体:

1-汽车+内燃机+方向盘

2-平面+ JetEngine +轭

如果你的程序不使用产品族,那么你就不需要抽象工厂。

同样,很多人混淆了抽象工厂模式和简单的工厂类声明为抽象。不要那样做!

裁判:https://refactoring.guru/design-patterns/factory-comparison

比起工厂方法,我更喜欢抽象工厂。从Tom Dalling上面的例子(顺便说一句,解释得很好)中,我们可以看到抽象工厂是更可组合的,因为我们所需要做的只是将一个不同的工厂传递给构造函数(这里使用构造函数依赖注入)。但是工厂方法要求我们引入一个新类(需要管理更多的东西)并使用子类化。总是选择组合而不是继承。

两者的区别

“工厂方法”和“抽象工厂”的主要区别在于,工厂方法是方法,而抽象工厂是对象。我想很多人都把这两个词搞混了,开始交替使用。我记得当我学习它们的时候,我很难找到它们之间的确切区别。

因为工厂方法只是一个方法,它可以在子类中被重写,因此引用的后半部分:

... 工厂方法模式使用的 继承并依赖于一个子类 来处理所需的对象 实例化。

引用假设对象在这里调用自己的工厂方法。因此,唯一可以改变返回值的是子类。

抽象工厂是一个具有多个工厂方法的对象。看看你引言的前半部分:

... 使用抽象工厂模式,一个类 委托对象的职责 实例化到另一个对象 作文……

他们说的是,有一个对象A,想要创建一个Foo对象。而不是创建Foo对象本身(例如,使用工厂方法),它将获得一个不同的对象(抽象工厂)来创建Foo对象。

代码示例

为了向你展示区别,这里有一个正在使用的工厂方法:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

这是一个正在使用的抽象工厂:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here