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

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。这就是使用继承来处理对象实例化的意思吗?

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

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


当前回答

抽象工厂与工厂方法的主要区别在于,抽象工厂是由组合实现的;但是工厂方法是通过继承实现的。

是的,您没有看错:这两种模式之间的主要区别在于古老的组合与继承之争。

UML图可以在(GoF)书中找到。我想提供代码示例,因为我认为将本文中前两个答案中的示例结合起来会比单独一个答案提供更好的演示。此外,我在类名和方法名中使用了书中的术语。

抽象工厂

The most important point to grasp here is that the abstract factory is injected into the client. This is why we say that Abstract Factory is implemented by Composition. Often, a dependency injection framework would perform that task; but a framework is not required for DI. The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below. And finally, the third point to note is the relationship between the products: in this case the outbound and reply queues. One concrete factory produces Azure queues, the other MSMQ. The GoF refers to this product relationship as a "family" and it's important to be aware that family in this case does not mean class hierarchy.

public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

工厂方法

The most important point to grasp here is that the ConcreteCreator is the client. In other words, the client is a subclass whose parent defines the factoryMethod(). This is why we say that Factory Method is implemented by Inheritance. The second critical point is to remember that the Factory Method Pattern is nothing more than a specialization of the Template Method Pattern. The two patterns share an identical structure. They only differ in purpose. Factory Method is creational (it builds something) whereas Template Method is behavioral (it computes something). And finally, the third point to note is that the Creator (parent) class invokes its own factoryMethod(). If we remove anOperation() from the parent class, leaving only a single method behind, it is no longer the Factory Method pattern. In other words, Factory Method cannot be implemented with less than two methods in the parent class; and one must invoke the other.

public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

混杂。&杂项工厂图案

请注意,尽管GoF定义了两种不同的工厂模式,但它们并不是唯一存在的工厂模式。它们甚至不一定是最常用的工厂模式。第三个著名的例子是Josh Bloch的《Effective Java》中的静态工厂模式。《头部优先设计模式》一书还包括另一种被称为简单工厂的模式。

不要落入假设每个工厂模式都必须匹配GoF中的一个模式的陷阱。

其他回答

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

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

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

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

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

在这种情况下,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.
    }
}

希望这能有所帮助。

抽象工厂与工厂方法的主要区别在于,抽象工厂是由组合实现的;但是工厂方法是通过继承实现的。

是的,您没有看错:这两种模式之间的主要区别在于古老的组合与继承之争。

UML图可以在(GoF)书中找到。我想提供代码示例,因为我认为将本文中前两个答案中的示例结合起来会比单独一个答案提供更好的演示。此外,我在类名和方法名中使用了书中的术语。

抽象工厂

The most important point to grasp here is that the abstract factory is injected into the client. This is why we say that Abstract Factory is implemented by Composition. Often, a dependency injection framework would perform that task; but a framework is not required for DI. The second critical point is that the concrete factories here are not Factory Method implementations! Example code for Factory Method is shown further below. And finally, the third point to note is the relationship between the products: in this case the outbound and reply queues. One concrete factory produces Azure queues, the other MSMQ. The GoF refers to this product relationship as a "family" and it's important to be aware that family in this case does not mean class hierarchy.

public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

工厂方法

The most important point to grasp here is that the ConcreteCreator is the client. In other words, the client is a subclass whose parent defines the factoryMethod(). This is why we say that Factory Method is implemented by Inheritance. The second critical point is to remember that the Factory Method Pattern is nothing more than a specialization of the Template Method Pattern. The two patterns share an identical structure. They only differ in purpose. Factory Method is creational (it builds something) whereas Template Method is behavioral (it computes something). And finally, the third point to note is that the Creator (parent) class invokes its own factoryMethod(). If we remove anOperation() from the parent class, leaving only a single method behind, it is no longer the Factory Method pattern. In other words, Factory Method cannot be implemented with less than two methods in the parent class; and one must invoke the other.

public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

混杂。&杂项工厂图案

请注意,尽管GoF定义了两种不同的工厂模式,但它们并不是唯一存在的工厂模式。它们甚至不一定是最常用的工厂模式。第三个著名的例子是Josh Bloch的《Effective Java》中的静态工厂模式。《头部优先设计模式》一书还包括另一种被称为简单工厂的模式。

不要落入假设每个工厂模式都必须匹配GoF中的一个模式的陷阱。

有相当多的定义。基本上,描述工厂模式的三种常用方法是

简单的工厂

基于条件的简单对象创建方法/类。

工厂方法

使用子类提供实现的工厂方法设计模式。

抽象工厂

抽象工厂设计模式产生相关或依赖的对象族,而不指定它们的具体类。

下面的链接非常有用-工厂比较-重构。guru

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

工厂设计模式

generation 1 <- generation 2 <- generation 3
//example
(generation 1) shape <- (generation 2) rectangle, oval <- (generation 3) rectangle impressionism, rectangle surrealism, oval impressionism, oval surrealism

工厂

用例:实例化第2代的一个对象

这是一种创造模式,允许你在一个简单的地方创建第2代。它符合SRP和OCP -所有的更改都在一个类中进行。

enum ShapeType {
    RECTANGLE,
    OVAL
}

class Shape {}

//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//Factory
class Factory {
    Shape createShape(ShapeType type) {

        switch (type) {
            case RECTANGLE:
                return new Rectangle();
            case OVAL:
                return new Oval();
        }
    }
}

//Creator
class Painter {

    private Factory factory;

    Painter(Factory factory) {
        this.factory = factory;
    }

    Shape prepareShape(ShapeType type) {
        return factory.createShape(type);
    }
}

//using
class Main {
    void main() {
        Painter painter = new Painter(new Factory());

        Shape shape1 = painter.prepareShape(ShapeType.RECTANGLE);
        Shape shape2 = painter.prepareShape(ShapeType.OVAL);
    }
}

工厂方法

用例:实例化第3代的一个对象

有助于与下一代家庭成员合作。每个画家都有自己的风格,印象派、超现实主义……工厂方法使用抽象创造者作为工厂(抽象方法),具体创造者是这种方法的实现

enum ShapeType {
    RECTANGLE,
    OVAL
}

class Shape {}

//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}

//Creator
abstract class Painter {

    Shape prepareShape(ShapeType type) {
        return createShape(type);
    }

    //Factory method
    abstract Shape createShape(ShapeType type);
}

//Concrete Creators
class PainterImpressionism {

    @override
    Shape createShape(ShapeType type) {
        switch (type) {
            case RECTANGLE:
                return new RectangleImpressionism();
            case OVAL:
                return new OvalImpressionism();
        }
    }
}

class PainterSurrealism {

    @override
    Shape createShape(ShapeType type) {
        switch (type) {
            case RECTANGLE:
                return new RectangleSurrealism();
            case OVAL:
                return new OvalSurrealism();
        }
    }
}

//using
class Main {
    void main() {
        Painter painterImpressionism = new PainterImpressionism();
        Shape shape1 = painterImpressionism.prepareShape(ShapeType.RECTANGLE);

        Painter painterSurrealism = new PainterSurrealism();
        Shape shape2 = painterSurrealism.prepareShape(ShapeType.RECTANGLE);
    }
}

抽象工厂

用例:实例化第3代的所有对象

工厂是抽象工厂和具象工厂的一部分


//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}

//Abstract Factory
interface Factory {
    Rectangle createRectangle();
    Oval createOval();
}

//Concrete Factories
class ImpressionismFactory implements Factory {
    @Override
    public Rectangle createRectangle() {
        return new RectangleImpressionism();
    }

    @Override
    public Oval createOval() {
        return new OvalImpressionism();
    }
}

class SurrealismFactory implements Factory {
    @Override
    public Rectangle createRectangle() {
        return new RectangleSurrealism();
    }

    @Override
    public Oval createOval() {
        return new OvalSurrealism();
    }
}

//Creator
class Painter {

    Rectangle rectangle;
    Oval oval;

    Painter(Factory factory) {
        rectangle = factory.createRectangle();
        rectangle.resize();

        oval = factory.createOval();
        oval.resize();
    }
}

//using
class Main {
    void main() {
        Painter painter1 = new Painter(new ImpressionismFactory());
        Shape shape1 = painter1.rectangle;
        Shape shape2 = painter1.oval;

        Painter painter2 = new Painter(new ImpressionismFactory());
        Shape shape3 = painter2.rectangle;
        Shape shape4 = painter1.oval;
    }
}