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

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

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

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


当前回答

抽象工厂:工厂中的工厂;将独立但相关/依赖的工厂分组在一起,而不指定它们的具体类的工厂。 抽象工厂实例

Factory:它提供了一种将实例化逻辑委托给子类的方法。 工厂模式示例

其他回答

抽象工厂创建了一个基类,其抽象方法定义了应该创建的对象的方法。派生基类的每个工厂类都可以创建每种对象类型的自己的实现。

工厂方法只是一个用于在类中创建对象的简单方法。它通常添加在聚合根中(Order类有一个名为CreateOrderLine的方法)

抽象工厂

在下面的示例中,我们设计了一个接口,这样我们就可以将队列创建与消息传递系统分离,因此可以为不同的队列系统创建实现,而不必更改代码库。

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

工厂方法

HTTP服务器的问题在于,我们总是需要为每个请求提供响应。

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

如果没有工厂方法,HTTP服务器用户(即程序员)将被迫使用特定于实现的类,这就违背了IHttpRequest接口的目的。

因此,我们引入工厂方法,以便响应类的创建也被抽象出来。

总结

区别在于,包含工厂方法的类的预期目的不是创建对象,而抽象工厂应该只用于创建对象。

使用工厂方法时应该小心,因为在创建对象时很容易破坏LSP(里斯科夫替换原则)。

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

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

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中的一个模式的陷阱。

抽象工厂:工厂中的工厂;将独立但相关/依赖的工厂分组在一起,而不指定它们的具体类的工厂。 抽象工厂实例

Factory:它提供了一种将实例化逻辑委托给子类的方法。 工厂模式示例

请允许我准确地说。大多数答案都已经解释过了,还提供了图表和例子。

所以我的回答就是一句话。我的原话是:“抽象工厂模式在抽象层上添加了多个工厂方法实现。它意味着一个抽象工厂包含或组合一个或多个工厂方法模式。

A)工厂方法模式

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

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

B)抽象工厂模式

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

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

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

2-平面+ JetEngine +轭

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

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

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