抽象工厂和工厂设计模式有什么区别?

发布于 2024-11-02 18:43:57 字数 603 浏览 1 评论 0原文

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

从我读到的内容来看,我发现工厂方法模式允许您定义如何创建单个具体产品,但对客户端隐藏实现,因为他们将看到通用产品。我的第一个问题是关于抽象工厂的。它的作用是允许您创建一系列具体对象(这可能取决于您使用的特定工厂)而不仅仅是单个具体对象?抽象工厂是否只返回一个非常大的对象或许多对象,具体取决于您调用的方法?

我的最后两个问题是关于我在很多地方看到的一个我无法完全理解的单引号:

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

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

现在,关于那句话,抽象工厂模式究竟如何通过组合将对象实例化的责任委托给另一个对象?这意味着什么?在我看来,抽象工厂模式也使用继承来完成构建过程,但话又说回来,我仍在学习这些模式。

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

I know there are many posts out there about the differences between these two patterns, but there are a few things that I cannot find.

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?

My final two questions are about a single quote that I cannot fully understand that I have seen in numerous places:

One difference between the two is that
with the Abstract Factory pattern, a
class delegates the responsibility of
object instantiation to another object
via composition whereas the Factory
Method pattern uses inheritance and
relies on a subclass to handle the
desired object instantiation.

My understanding is that the factory method pattern has a Creator interface that will make the ConcreteCreator be in charge of knowing which ConcreteProduct to instantiate. Is this what it means by using inheritance to handle object instantiation?

Now with regards to that quote, how exactly does the Abstract Factory pattern delegate the responsibility of object instantiation to another object via composition? What does this mean? It looks like the Abstract Factory pattern also uses inheritance to do the construction process as well in my eyes, but then again I am still learning about these patterns.

Any help especially with the last question, would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(21

神经暖 2024-11-09 18:43:57

两者的区别

“工厂方法”和“抽象工厂”之间的主要区别在于,工厂方法是方法,而抽象工厂是对象。我认为很多人混淆了这两个术语,并开始互换使用它们。我记得当我学习它们时,我很难准确地找出它们之间的区别。

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

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

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

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

...用抽象工厂模式,一个类
委托对象的责任
通过实例化到另一个对象
组成...

他们所说的是有一个对象 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

The Difference Between The Two

The main difference between a "factory method" and an "abstract factory" is that the factory method is a method, and an abstract factory is an object. I think a lot of people get these two terms confused, and start using them interchangeably. I remember that I had a hard time finding exactly what the difference was when I learnt them.

Because the factory method is just a method, it can be overridden in a subclass, hence the second half of your quote:

... the Factory Method pattern uses
inheritance and relies on a subclass
to handle the desired object
instantiation.

The quote assumes that an object is calling its own factory method here. Therefore the only thing that could change the return value would be a subclass.

The abstract factory is an object that has multiple factory methods on it. Looking at the first half of your quote:

... with the Abstract Factory pattern, a class
delegates the responsibility of object
instantiation to another object via
composition ...

What they're saying is that there is an object A, who wants to make a Foo object. Instead of making the Foo object itself (e.g., with a factory method), it's going to get a different object (the abstract factory) to create the Foo object.

Code Examples

To show you the difference, here is a factory method in use:

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();
    }
}

And here is an abstract factory in use:

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
眼泪都笑了 2024-11-09 18:43:57

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

在此处输入图像描述

工厂方法只是一个简单的方法用于在类中创建对象。它通常添加在聚合根中(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 (创建对象时的里氏替换原则)。

Abstract factory creates a base class with abstract methods defining methods for the objects that should be created. Each factory class which derives the base class can create their own implementation of each object type.

enter image description here

Factory method is just a simple method used to create objects in a class. It's usually added in the aggregate root (The Order class has a method called CreateOrderLine)

enter image description here

Abstract factory

In the example below we design an interface so that we can decouple queue creation from a messaging system and can therefore create implementations for different queue systems without having to change the code base.

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(/*....*/);
      }
}

Factory method

The problem in HTTP servers is that we always need an response for every request.

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

    IHttpResponse CreateResponse(int httpStatusCode);
}

Without the factory method, the HTTP server users (i.e. programmers) would be forced to use implementation specific classes which defeat the purpose of the IHttpRequest interface.

Therefore we introduce the factory method so that the creation of the response class also is abstracted away.

Summary

The difference is that the intended purpose of the class containing a factory method is not to create objects, while an abstract factory should only be used to create objects.

One should take care when using factory methods since it's easy to break the LSP (Liskov Substitution principle) when creating objects.

国产ˉ祖宗 2024-11-09 18:43:57

AbstractFactory 和 Factory 设计模式之间的区别如下:

  • 工厂方法仅用于创建一种产品,而Abstract Factory用于创建相关产品系列或相关产品。
  • 工厂方法模式向客户端公开用于创建对象的方法,而在抽象工厂的情况下,它们公开一系列可能由这些工厂方法组成的相关对象。
  • 工厂方法模式隐藏单个对象的构造,而抽象工厂隐藏一系列相关对象的构造。抽象工厂通常使用(一组)工厂方法来实现。
  • 抽象工厂模式使用组合将创建对象的责任委托给另一个类,而工厂方法设计模式使用继承并依赖派生类或子类来创建对象。
  • 工厂方法模式背后的想法是,它允许客户端不知道在运行时需要创建哪些具体类,而只想获得一个可以执行的类的情况当您的系统必须创建多个产品系列或者您想要提供一个产品库而不暴露实现细节时,最好利用抽象工厂模式。

工厂方法模式实现: 工厂方法 UML

抽象工厂模式实现: >

抽象工厂 UML

Difference between AbstractFactory and Factory design patterns are as follows:

  • Factory Method is used to create one product only but Abstract Factory is about creating families of related or dependent products.
  • Factory Method pattern exposes a method to the client for creating the object whereas in the case of Abstract Factory they expose a family of related objects which may consist of these Factory methods.
  • Factory Method pattern hides the construction of a single object whereas Abstract Factory hides the construction of a family of related objects. Abstract factories are usually implemented using (a set of) factory methods.
  • Abstract Factory pattern uses composition to delegate the responsibility of creating an object to another class while Factory Method design pattern uses inheritance and relies on a derived class or subclass to create an object.
  • The idea behind the Factory Method pattern is that it allows for the case where a client doesn't know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job while Abstract Factory pattern is best utilized when your system has to create multiple families of products or you want to provide a library of products without exposing the implementation details.!

Factory Method Pattern Implementation: Factory Method UML

Abstract Factory Pattern Implementation:

Abstract Factory UML

泪是无色的血 2024-11-09 18:43:57

Abstract Factory 和 Factory Method 的主要区别在于Abstract Factory 是通过 Composition 实现的;但是工厂方法是通过继承实现的

是的,您没有看错:这两种模式之间的主要区别是旧的组合与继承辩论。

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

抽象工厂

  1. 这里最需要掌握的一点是,抽象工厂
    注入到客户端。这就是为什么我们说抽象
    工厂是通过组合来实现的。通常,依赖注入
    框架将执行该任务;但不需要框架
    对于DI。
  2. 第二个关键点是这里的具体工厂是
    不是工厂方法实现!工厂的示例代码
    下面进一步示出方法。
  3. 最后,第三点需要注意的是
    产品:在本例中为出站和回复队列。一混凝土
    工厂生产Azure队列,另一个生产MSMQ。 GoF指的是
    这种产品关系就像一个“家庭”,这一点很重要
    请注意,这里的家庭并不意味着阶级等级制度。
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();
    }
}

工厂方法

  1. 这里要掌握的最重要的一点是ConcreteCreator
    客户。换句话说,客户端是一个子类,其父类定义了factoryMethod()。这就是为什么我们这么说
    工厂方法是通过继承来实现的。
  2. 第二个关键点是要记住工厂方法
    模式只不过是模板方法的特化
    图案。这两种模式具有相同的结构。他们只
    目的不同。工厂方法是创造性的(它构建
    某事)而模板方法是行为性的(它计算
    某物)。
  3. 最后,第三点需要注意的是 Creator (父级)
    类调用它自己的factoryMethod()。如果我们删除
    anOperation() 来自父类,只留下一个方法
    后面,就不再是Factory Method模式了。换句话说,
    工厂方法不能用少于两个方法来实现
    父类;并且一个必须调用另一个。
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 定义了两种不同的工厂模式,但它们并不是唯一存在的工厂模式。它们甚至不一定是最常用的工厂模式。第三个著名的例子是来自Effective Java 的Josh Bloch 的静态工厂模式。 《Head First Design Patterns》一书还包含另一种模式,他们称之为“简单工厂”。

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

The main difference between Abstract Factory and Factory Method is that Abstract Factory is implemented by Composition; but Factory Method is implemented by Inheritance.

Yes, you read that correctly: the main difference between these two patterns is the old composition vs inheritance debate.

UML diagrams can be found in the (GoF) book. I want to provide code examples, because I think combining the examples from the top two answers in this thread will give a better demonstration than either answer alone. Additionally, I have used terminology from the book in class and method names.

Abstract Factory

  1. 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.
  2. The second critical point is that the concrete factories here are
    not
    Factory Method implementations! Example code for Factory
    Method is shown further below.
  3. 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();
    }
}

Factory Method

  1. 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.
  2. 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).
  3. 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();
    }
}

Misc. & Sundry Factory Patterns

Be aware that although the GoF define two different Factory patterns, these are not the only Factory patterns in existence. They are not even necessarily the most commonly used Factory patterns. A famous third example is Josh Bloch's Static Factory Pattern from Effective Java. The Head First Design Patterns book includes yet another pattern they call Simple Factory.

Don't fall into the trap of assuming every Factory pattern must match one from the GoF.

只有一腔孤勇 2024-11-09 18:43:57

Abstract Factory是用于创建相关产品的接口,而Factory Method只是一种方法。抽象工厂可以通过多个工厂方法来实现。

抽象工厂 UML

Abstract Factory is an interface for creating related products, but Factory Method is only one method. Abstract Factory can be implemented by multiple Factory Methods.

Abstract Factory UML

小兔几 2024-11-09 18:43:57

考虑这个例子以便于理解。

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

一般来说,您在这里要做的是,通过您的工厂方法创建产品,即宽带、电话线和移动设备,您知道这些产品拥有哪些属性,而且非常简单。

现在,该公司希望向客户提供一系列产品,即宽带、电话线和移动设备,这就需要抽象工厂来发挥作用。

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

在本例中,BundleFactory 是抽象工厂,BroadbandFactoryPhonelineFactoryMobileFactoryFactory。为了更加简化,这些工厂将使用工厂方法来初始化各个产品。

请参阅下面的代码示例:

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.
    }
}

希望这会有所帮助。

Consider this example for easy understanding.

What does telecommunication companies provide? Broadband, phone line and mobile for instance and you're asked to create an application to offer their products to their customers.

Generally what you'd do here is, creating the products i.e broadband, phone line and mobile are through your Factory Method where you know what properties you have for those products and it's pretty straightforward.

Now, the company wants to offer their customer a bundle of their products i.e broadband, phone line, and mobile altogether, and here comes the Abstract Factory to play.

Abstract Factory is, in other words, are the composition of other factories who are responsible for creating their own products and Abstract Factory knows how to place these products in more meaningful in respect of its own responsibilities.

In this case, the BundleFactory is the Abstract Factory, BroadbandFactory, PhonelineFactory and MobileFactory are the Factory. To simplify more, these Factories will have Factory Method to initialise the individual products.

Se the code sample below:

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.
    }
}

Hope this helps.

没有你我更好 2024-11-09 18:43:57

工厂方法依赖于继承:对象创建委托给子类,子类实现工厂方法来创建对象。

抽象工厂依赖于对象组合:对象创建是在工厂接口中公开的方法中实现的。

工厂和抽象工厂模式的高级图,

diagram

有关工厂方法的更多信息,请参阅 本文

有关抽象工厂方法的更多信息,请参阅本文

Factory Method relies on inheritance: Object creation is delegated to subclasses, which implement the factory method to create objects.

Abstract Factory relies on object composition: object creation is implemented in methods exposed in the factory interface.

High level diagram of Factory and Abstract factory pattern,

diagram

For more information about the Factory method, refer this article.

For more information about Abstract factory method, refer this article.

对岸观火 2024-11-09 18:43:57

现实生活中的例子。 (容易记住)

工厂

想象一下你正在建造一座房子,你向木匠寻求一扇门。您给出门的尺寸和您的要求,他将为您建造一扇门。在这种情况下,木匠是一家门工厂。您的规格是工厂的输入,而门是工厂的输出或产品。

抽象工厂

现在,考虑相同的门示例。你可以去找木匠,也可以去塑料门店或者PVC店。都是门厂。根据情况,您决定需要联系什么样的工厂。这就像一个抽象工厂。

我在这里解释了工厂方法模式和抽象工厂模式,首先不使用它们解释问题,然后使用上述模式解决问题
https://github.com/vikramnagineni/Design-Patterns/tree/master

Real Life Example. (Easy to remember)

Factory

Imagine you are constructing a house and you approach a carpenter for a door. You give the measurement for the door and your requirements, and he will construct a door for you. In this case, the carpenter is a factory of doors. Your specifications are inputs for the factory, and the door is the output or product from the factory.

Abstract Factory

Now, consider the same example of the door. You can go to a carpenter, or you can go to a plastic door shop or a PVC shop. All of them are door factories. Based on the situation, you decide what kind of factory you need to approach. This is like an Abstract Factory.

I have explained here both Factory method pattern and abstract factory pattern beginning with not using them explaining issues and then solving issues by using the above patterns
https://github.com/vikramnagineni/Design-Patterns/tree/master

捶死心动 2024-11-09 18:43:57

那里有很多定义。基本上,描述工厂模式的三种常见方式是

  1. 简单工厂

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

  1. 工厂方法

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

  1. 抽象工厂

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

下面的链接非常有用 - 工厂比较 - refactoring.guru

There are quite a few definitions out there. Basically, the three common way of describing factory pattern are

  1. Simple Factory

Simple object creation method/class based on a condition.

  1. Factory Method

The Factory Method design pattern using subclasses to provide the implementation.

  1. Abstract Factory

The Abstract Factory design pattern producing families of related or dependent objects without specifying their concrete classes.

The below link was very useful - Factory Comparison - refactoring.guru

西瓜 2024-11-09 18:43:57

1.我的第一个问题是关于抽象工厂的。它的作用是允许您在其中创建一系列具体对象(这可能取决于您使用的特定工厂)而不仅仅是单个具体对象?

是的。抽象工厂的意图是:

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


2.抽象工厂是否只返回一个非常大的对象或许多对象,具体取决于您调用的方法?

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

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

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

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

AbstractFactory 定义了一个 FactoryMethod,ConcreteFactory 负责构建一个 ConcreteProduct。

只需按照 James Sugrue 撰写的这篇 dzone 文章中的代码示例进行操作即可。

您可以在相关的 SE 帖子中找到更多详细信息:

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

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

1. 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?

Yes. The intent of Abstract Factory is:

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.


2. Does the abstract factory only return one very large object or many objects depending on what methods you call?

Ideally it should return one object per the method client is invoking.

3. My understanding is that the factory method pattern has a Creator interface that will make the ConcreteCreator be in charge of knowing which ConcreteProduct to instantiate. Is this what it means by using inheritance to handle object instantiation?

Yes. Factory method uses inheritance.

4. Abstract Factory pattern delegate the responsibility of object instantiation to another object via composition? What does this mean?

AbstractFactory defines a FactoryMethod and ConcreteFactory is responsible for building a ConcreteProduct.

Just follow through the code example in this dzone article by by James Sugrue.

You can find more details in related SE posts:

What is the basic difference between the Factory and Abstract Factory Design Patterns?

Design Patterns: Factory vs Factory method vs Abstract Factory

滿滿的愛 2024-11-09 18:43:57

了解动机的差异:

假设您正在构建一个工具,其中包含对象和对象相互关系的具体实现。由于您预见了对象的变化,因此您通过将创建对象变体的责任分配给另一个对象(我们称之为抽象工厂)来创建间接寻址。这种抽象具有很大的好处,因为您预见到未来的扩展需要这些对象的变体。

这种思路的另一个相当有趣的动机是整个组中的每个对象或没有一个对象将具有相应的变体。根据某些条件,将使用任一变体,并且在每种情况下所有对象都必须具有相同的变体。这可能有点违反直觉,因为我们通常倾向于认为 - 只要对象的变体遵循共同的统一契约(更广泛意义上的接口),具体的实现代码就永远不会中断。这里有趣的事实是,并不总是如此,特别是当预期行为无法通过编程契约建模时。

一个简单的例子(借用 GoF 的想法)是任何 GUI 应用程序,例如模拟 MS、Mac 或 Fedora 操作系统外观的虚拟监视器。在这里,例如,当所有窗口、按钮等小部件对象除了从MAC变体派生的滚动条之外都具有MS变体时,该工具的目的就严重失败了。

以上这些案例构成了抽象工厂模式的根本需求。

另一方面,假设您正在编写一个框架,以便许多人可以使用您的框架构建各种工具(例如上面示例中的工具)。根据框架的想法,您不需要这样做,尽管您不能在逻辑中使用具体对象。您宁愿在各种对象之间以及它们的交互方式之间放置一些高级契约。虽然您(作为框架开发人员)仍处于非常抽象的级别,但该工具的每个构建者都被迫遵循您的框架构造。然而,他们(工具构建者)可以自由地决定要构建什么对象以及他们创建的所有对象如何交互。与前面的情况(抽象工厂模式)不同,您(作为框架创建者)在这种情况下不需要使用具体对象;而可以停留在对象的契约级别。此外,与前面动机的第二部分不同,您或工具构建者永远不会遇到混合来自变体的对象的情况。在这里,虽然框架代码仍处于合同级别,但每个工具构建者都受到限制(受案例本身的性质)使用自己的对象。在这种情况下,对象创建被委托给每个实现者,框架提供者只提供用于创建和返回对象的统一方法。这些方法对于框架开发人员继续他们的代码是不可避免的,并且有一个特殊的名称,称为工厂方法底层模式的工厂方法模式)。

一些注释:

  • 如果您熟悉“模板方法”,那么您会发现在与任何形式的框架相关的程序中,工厂方法通常是从模板方法调用的。相比之下,应用程序的模板方法通常是特定算法的简单实现,并且没有工厂方法。
  • 此外,为了思想的完整性,使用框架(上面提到),当工具构建者在每个工厂方法内部构建工具时,他/她可以不创建具体对象,而是可以如果工具构建者预见到未来扩展的具体对象的变化,则进一步将责任委托给抽象工厂对象。

示例代码:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}

Understand the differences in the motivations:

Suppose you’re building a tool where you’ve objects and a concrete implementation of the interrelations of the objects. Since you foresee variations in the objects, you’ve created an indirection by assigning the responsibility of creating variants of the objects to another object (we call it abstract factory). This abstraction finds strong benefit since you foresee future extensions needing variants of those objects.

Another rather intriguing motivation in this line of thoughts is a case where every-or-none of the objects from the whole group will have a corresponding variant. Based on some conditions, either of the variants will be used and in each case all objects must be of same variant. This might be a bit counter intuitive to understand as we often tend think that - as long as the variants of an object follow a common uniform contract (interface in broader sense), the concrete implementation code should never break. The intriguing fact here is that, not always this is true especially when expected behavior cannot be modeled by a programming contract.

A simple (borrowing the idea from GoF) is any GUI applications say a virtual monitor that emulates look-an-feel of MS or Mac or Fedora OS’s. Here, for example, when all widget objects such as window, button, etc. have MS variant except a scroll-bar that is derived from MAC variant, the purpose of the tool fails badly.

These above cases form the fundamental need of Abstract Factory Pattern.

On the other hand, imagine you’re writing a framework so that many people can built various tools (such as the one in above examples) using your framework. By the very idea of a framework, you don’t need to, albeit you could not use concrete objects in your logic. You rather put some high level contracts between various objects and how they interact. While you (as a framework developer) remain at a very abstract level, each builders of the tool is forced to follow your framework-constructs. However, they (the tool builders) have the freedom to decide what object to be built and how all the objects they create will interact. Unlike the previous case (of Abstract Factory Pattern), you (as framework creator) don’t need to work with concrete objects in this case; and rather can stay at the contract level of the objects. Furthermore, unlike the second part of the previous motivations, you or the tool-builders never have the situations of mixing objects from variants. Here, while framework code remains at contract level, every tool-builder is restricted (by the nature of the case itself) to using their own objects. Object creations in this case is delegated to each implementer and framework providers just provide uniform methods for creating and returning objects. Such methods are inevitable for framework developer to proceed with their code and has a special name called Factory method (Factory Method Pattern for the underlying pattern).

Few Notes:

  • If you’re familiar with ‘template method’, then you’d see that factory methods are often invoked from template methods in case of programs pertaining to any form of framework. By contrast, template methods of application-programs are often simple implementation of specific algorithm and void of factory-methods.
  • Furthermore, for the completeness of the thoughts, using the framework (mentioned above), when a tool-builder is building a tool, inside each factory method, instead of creating a concrete object, he/she may further delegate the responsibility to an abstract-factory object, provided the tool-builder foresees variations of the concrete objects for future extensions.

Sample Code:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}
自此以后,行同陌路 2024-11-09 18:43:57

工厂设计模式

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代一个对象

它是一个创意 模式允许您在一个简单的地方创建第二代。它符合 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代一个对象

有助于与下一代家庭成员合作。每个画家都有自己的风格,比如印象派、超现实主义……Factory Method使用抽象的Creator作为Factory(抽象方法)和Concrete Creators的实现此方法的

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代所有对象

工厂是抽象的一部分FactoryConcrete Factories 中的实现


//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;
    }
}

Factory Design Pattern

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

Factory

Use case: instantiate one object of generation 2

It is a Creational pattern which allows you to create generation 2 in a simple place. It conforms SRP and OCP - all changes are made in a single class.

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);
    }
}

Factory method

Use case: instantiate one object of generation 3

Helps to work with next generation of family members. Every painter has his own style like Impressionism, Surrealism... Factory Method uses abstract Creator as Factory(abstract method) and Concrete Creators are realizations of this method

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);
    }
}

Abstract Factory

Use case: instantiate all objects of generation 3

Factory is a part of abstract Factory and realisations in Concrete Factories


//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;
    }
}
萌面超妹 2024-11-09 18:43:57

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

Let us put it clear that most of the time in production code, we use abstract factory pattern because class A is programmed with interface B. And A needs to create instances of B. So A has to have a factory object to produce instances of B. So A is not dependent on any concrete instance of B. Hope it helps.

极致的悲 2024-11-09 18:43:57

以最少的界面和简单的方式使其变得非常简单请关注“//1”:

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

这里重点: 1.工厂& AbstractFactory机制必须使用继承(System.Object->byte、float...);所以如果你在程序中有继承,那么工厂(抽象工厂很可能不会在那里)已经被设计为2。创建者(MyFactory)知道具体类型,因此将具体类型对象返回给调用者(Main);在抽象工厂中,返回类型将是一个接口。

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

要点: 1. 要求:本田将创建“Regular”、“Sports”,而 Hero 将创建“DarkHorse”、“Sports”和“Scooty”。 2.为什么有两个接口?一个用于制造商类型(IVehicleFactory),另一个用于产品工厂(IVehicle);理解 2 个接口的另一种方式是抽象工厂就是创建相关对象 2。 问题是 IVehicleFactory 的子级返回 IVehicle(而不是工厂中的具体对象);所以我得到父变量(IVehicle);然后我通过调用 CreateSingleVehicle 创建实际的具体类型,然后将父对象转换为实际的子对象。如果我这样做 RegularBike HeroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; 会发生什么?你会得到ApplicationException,这就是为什么我们需要通用抽象工厂,如果需要的话我会解释一下。希望它对初学者到中级观众有所帮助。

To make it very simple with minimum interface & please focus "//1":

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

Here important points: 1. Factory & AbstractFactory mechanisms must use inheritance (System.Object-> byte, float ...); so if you have inheritance in program then Factory(Abstract Factory would not be there most probably) is already there by design 2. Creator (MyFactory) knows about concrete type so returns concrete type object to caller(Main); In abstract factory return type would be an Interface.

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

Important points: 1. Requirement: Honda would create "Regular", "Sports" but Hero would create "DarkHorse", "Sports" and "Scooty". 2. why two interfaces? One for manufacturer type(IVehicleFactory) and another for product factory(IVehicle); other way to understand 2 interfaces is abstract factory is all about creating related objects 2. The catch is the IVehicleFactory's children returning and IVehicle(instead of concrete in factory); so I get parent variable(IVehicle); then I create actual concrete type by calling CreateSingleVehicle and then casting parent object to actual child object. What would happen if I do RegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; you will get ApplicationException and that's why we need generic abstract factory which I would explain if required. Hope it helps from beginner to intermediate audience.

策马西风 2024-11-09 18:43:57

A) 工厂方法模式

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

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

B) 抽象工厂模式

抽象工厂是一种创建型设计模式,允许生成相关或依赖对象系列,而无需指定它们的具体类。

什么是“对象族”?例如,采用这组类:Transport + Engine + Controls。这些可能有几种变体:

1- 汽车 + CombustionEngine + SteeringWheel

2- 飞机 + JetEngine + Yoke

如果您的程序不与产品系列一起运行,那么您不需要抽象工厂。

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

参考:https://refactoring.guru/design-patterns/factory-comparison

A) Factory Method pattern

The Factory Method is a creational design pattern that provides an interface for creating objects but allows subclasses to alter the type of an object that will be created.

If you have a creation method in base class and subclasses that extend it, you might be looking at the factory method.

B)Abstract Factory pattern

The Abstract Factory is a creational design pattern that allows producing families of related or dependent objects without specifying their concrete classes.

What are the "families of objects"? For instance, take this set of classes: Transport + Engine + Controls. There are might be several variants of these:

1- Car + CombustionEngine + SteeringWheel

2- Plane + JetEngine + Yoke

If your program doesn’t operate with product families, then you don’t need an abstract factory.

And again, a lot of people mix-up the abstract factory pattern with a simple factory class declared as abstract. Don’t do that!

REF: https://refactoring.guru/design-patterns/factory-comparison

仙女山的月亮 2024-11-09 18:43:57

在我看来,@TomDalling 给出的答案确实是正确的(就其价值而言),但是评论中似乎仍然存在很多混乱。

我在这里所做的是创建这两种模式的一些稍微非典型的示例,并试图使它们乍一看非常相似。这将有助于查明区分它们的关键差异。

工厂方法Abstract Factory

如果您对这些模式完全陌生,那么这些示例可能不是最好的起点。

工厂方法

在此处输入图像描述

Client.javaish

Client(Creator creator) {
    ProductA a = creator.createProductA();
}

Creator.javaish

Creator() {}

void creatorStuff() {
    ProductA a = createProductA();
    a.doSomething();
    ProductB b = createProductB();
    b.doStuff();
}

abstract ProductA createProductA();

ProductB createProductB() {
    return new ProductB1();
}

为什么会有 CreatorClient

为什么不呢? FactoryMethod 可以与两者一起使用,但将由 Creator 的类型决定创建的特定产品。

为什么 createProductBCreator 中不是抽象的?

可以提供默认实现,子类仍然可以重写该方法以提供自己的实现。

我以为工厂方法只能创建一种产品?

每个方法确实只返回一种产品,但创建者可以使用多个工厂方法,它们只是不一定以任何特定方式相关。

抽象工厂

在此处输入图像描述

Client.javaish

AbstractFactory factory;

Client() {
    if (MONDAY) {
        factory = new Factory2();
    } else {
        factory = new AbstractFactory();
    }
}

void clientStuff() {
    ProductA a = factory.createProductA();
    a.doSomething();
    ProductB b = factory.createProductB();
    b.doStuff();
}

等等!您的 AbstractFactory 不是,嗯...呃 Abstract

没关系,我们仍然提供一个接口。创建方法的返回类型是我们想要制作的产品的超类型。

圣烟蝙蝠侠! Factory2 不会覆盖 createProductA(),“产品系列”发生了什么?

该模式中没有任何内容表明一个对象不能属于多个系列(尽管您的用例可能会禁止它)。每个混凝土工厂负责决定哪些产品可以一起生产。

这是不对的,Client 没有使用依赖注入,

你必须决定你的具体类将在什么地方,Client 仍然被写入AbstractFactory 接口。

这里的困惑在于人们将组合依赖注入混为一谈。 Client 拥有一个 AbstractFactory,无论它是如何获得的。与 IS-A 关系相反,ClientAbstractFactory 之间没有继承关系。

主要区别

  • 抽象工厂始终与对象族有关
  • 工厂方法只是一种允许子类指定具体对象类型的方法
  • 抽象工厂为客户端提供接口,并且与产品的使用位置分开,工厂方法可以由创建者本身使用或暴露给客户端。

摘要

工厂的目的是向客户端或自身提供对象。

创建者有自己的责任,可能需要使用对象或将它们传递给客户端

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

仅抽象工厂:

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


PlantUML 代码(如果您想使用图表):

@startuml FactoryMethod
abstract class Creator {
    creatorStuff()
    {abstract} createProductA(): ProductA
    createProductB(): ProductB
}
class Creator1 {
    createProductA(): ProductA
}
class Creator2 {
    createProductA(): ProductA
    createProductB(): ProductB
}

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
    ' class Product1B
}
together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}
Client --> Creator

Creator <|-- Creator1
Creator <|-- Creator2

Creator --> ProductB1
ProductA1 <-- Creator1
ProductA1 <-- Creator2
ProductB2 <-- Creator2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

ProductA <- Creator

@enduml
@startuml AbstractFactory

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
}

together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}

class AbstractFactory {
    createProductA(): ProductA
    createProductB(): ProductB
    --
    -
}

class Factory2 {
    createProductB(): ProductB
}

Client --> AbstractFactory
AbstractFactory <|-- Factory2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

AbstractFactory --> ProductA1
AbstractFactory --> ProductB1
ProductB2 <-- Factory2

@enduml

In my estimation the answer given by @TomDalling is indeed correct (for what it's worth), however there still seems to be a lot of confusion in the comments.

What I've done here is create some slightly atypical examples of the two patterns and tried to make them appear at first glance quite similar. This will help to pinpoint the crtical differences that separate them.

Factory MethodAbstract Factory

If you're completely new to the patterns these examples are propably not the best place to start.

Factory Method

enter image description here

Client.javaish

Client(Creator creator) {
    ProductA a = creator.createProductA();
}

Creator.javaish

Creator() {}

void creatorStuff() {
    ProductA a = createProductA();
    a.doSomething();
    ProductB b = createProductB();
    b.doStuff();
}

abstract ProductA createProductA();

ProductB createProductB() {
    return new ProductB1();
}

Why is there a Creator and a Client?

Why not? The FactoryMethod can be used with both, but it will be the type of Creator that determines the specific product created.

Why isn't createProductB abstract in Creator?

A default implementation can be provided, subclasses can still override the method to provide their own implementation.

I thought factory methods only create one product?

Each method does return just one product, but the creator can use multiple factory methods, they just aren't necessarily related in any particular way.

Abstract Factory

enter image description here

Client.javaish

AbstractFactory factory;

Client() {
    if (MONDAY) {
        factory = new Factory2();
    } else {
        factory = new AbstractFactory();
    }
}

void clientStuff() {
    ProductA a = factory.createProductA();
    a.doSomething();
    ProductB b = factory.createProductB();
    b.doStuff();
}

Wait! Your AbstractFactory isn't, well... er Abstract

That's okay, we're still providing an interface. The return types on the create methods are super-types of the products we want to make.

Holy Smoke Batman! Factory2 doesn't override createProductA(), what happened to "families of products"?

There's nothing in the pattern that says an object can't belong to more than one family (although your use case might prohibit it). Each concrete factory is responsible for deciding which products are allowed to be created together.

That can't be right, the Client isn't using dependency injection

You've got to decide what your concrete classes will be somewhere, the Client is still written to the AbstractFactory interface.

The confusion here is that people conflate composition with dependency injection. The Client HAS-A AbstractFactory regardless of how it got it. Contrast with the IS-A relationship, Client and AbstractFactory have no inheritance between them.

Key Differences

  • Abstract Factory is always about families of objects
  • Factory Method is just a method that allows subclasses to specify the type of concrete object
  • Abstract Factory provides an interface to a Client and is separate from where the products are used, the Factory Method could be used by the Creator itself or exposed to a Client.

Summary

The purpose of a factory is to provide a objects, either to a client or itself.

A creator has its own responsibilities and may need to use objects or pass them to a client

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. - GoF

An abstract factory only:

Provide[s] an interface for creating families of related or dependent objects without specifying their concrete classes. - GoF


PlantUML code if you want to play with the diagrams:

@startuml FactoryMethod
abstract class Creator {
    creatorStuff()
    {abstract} createProductA(): ProductA
    createProductB(): ProductB
}
class Creator1 {
    createProductA(): ProductA
}
class Creator2 {
    createProductA(): ProductA
    createProductB(): ProductB
}

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
    ' class Product1B
}
together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}
Client --> Creator

Creator <|-- Creator1
Creator <|-- Creator2

Creator --> ProductB1
ProductA1 <-- Creator1
ProductA1 <-- Creator2
ProductB2 <-- Creator2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

ProductA <- Creator

@enduml
@startuml AbstractFactory

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
}

together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}

class AbstractFactory {
    createProductA(): ProductA
    createProductB(): ProductB
    --
    -
}

class Factory2 {
    createProductB(): ProductB
}

Client --> AbstractFactory
AbstractFactory <|-- Factory2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

AbstractFactory --> ProductA1
AbstractFactory --> ProductB1
ProductB2 <-- Factory2

@enduml
神仙妹妹 2024-11-09 18:43:57

任何时候我都更喜欢抽象工厂而不是工厂方法。从上面 Tom Dalling 的示例(顺便说一句,很好的解释)中,我们可以看到抽象工厂更具可组合性,因为我们需要做的就是将不同的工厂传递给构造函数(此处使用构造函数依赖注入)。但工厂方法要求我们引入一个新类(需要管理更多的东西)并使用子类化。总是更喜欢组合而不是继承。

I would favor Abstract Factory over Factory Method anytime. From Tom Dalling's example (great explanation btw) above, we can see that Abstract Factory is more composable in that all we need to do is passing a different Factory to the constructor (constructor dependency injection in use here). But Factory Method requires us to introduce a new class (more things to manage) and use subclassing. Always prefer composition over inheritance.

寄与心 2024-11-09 18:43:57

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

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

Abstract Factory: A factory of factories; a factory that groups the individual but related/dependent factories together without specifying their concrete classes.
Abstract Factory Example

Factory: It provides a way to delegate the instantiation logic to child classes.
Factory Pattern Example

み零 2024-11-09 18:43:57

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

所以我的回答只是一句俏皮话。我自己的话:“抽象工厂模式在多个工厂方法实现上添加了抽象层。这意味着抽象工厂包含或复合一个或多个工厂方法模式”

Allow me to put it precisely. Most of the answers have already explained, provided diagrams and examples as well.

So my answer would just be a one-liner. My own words: “An abstract factory pattern adds on the abstract layer over multiple factory method implementations. It means an abstract factory contains or composite one or more than one factory method pattern”

我家小可爱 2024-11-09 18:43:57

之前的很多答案都没有提供抽象工厂和工厂方法模式之间的代码比较。下面我尝试通过Java来解释它。我希望它可以帮助需要简单解释的人。

正如 GoF 恰当地说:抽象工厂提供了一个用于创建系列的接口相关或依赖对象而不指定
他们的具体课程。

public class Client {
    public static void main(String[] args) {
        ZooFactory zooFactory = new HerbivoreZooFactory();
        Animal animal1 = zooFactory.animal1();
        Animal animal2 = zooFactory.animal2();
        animal1.sound();
        animal2.sound();

        System.out.println();

        AnimalFactory animalFactory = new CowAnimalFactory();
        Animal animal = animalFactory.createAnimal();
        animal.sound();
    }
}

public interface Animal {
    public void sound();
}

public class Cow implements Animal {

    @Override
    public void sound() {
        System.out.println("Cow moos");
    }
}

public class Deer implements Animal {

    @Override
    public void sound() {
        System.out.println("Deer grunts");
    }

}

public class Hyena implements Animal {

    @Override
    public void sound() {
        System.out.println("Hyena.java");
    }

}

public class Lion implements Animal {

    @Override
    public void sound() {
        System.out.println("Lion roars");
    }

}

public interface ZooFactory {
    Animal animal1();

    Animal animal2();
}

public class CarnivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Lion();
    }

    @Override
    public Animal animal2() {
        return new Hyena();
    }

}

public class HerbivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Cow();
    }

    @Override
    public Animal animal2() {
        return new Deer();
    }

}

public interface AnimalFactory {
    public Animal createAnimal();
}

public class CowAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Cow();
    }

}

public class DeerAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Deer();
    }

}

public class HyenaAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Hyena();
    }

}

public class LionAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Lion();
    }

}

A lot of the previous answers do not provide code comparisons between Abstract Factory and Factory Method pattern. The following is my attempt at explaining it via Java. I hope it helps someone in need of a simple explanation.

As GoF aptly says: Abstract Factory provides an interface for creating families of related or dependent objects without specifying
their concrete classes.

public class Client {
    public static void main(String[] args) {
        ZooFactory zooFactory = new HerbivoreZooFactory();
        Animal animal1 = zooFactory.animal1();
        Animal animal2 = zooFactory.animal2();
        animal1.sound();
        animal2.sound();

        System.out.println();

        AnimalFactory animalFactory = new CowAnimalFactory();
        Animal animal = animalFactory.createAnimal();
        animal.sound();
    }
}

public interface Animal {
    public void sound();
}

public class Cow implements Animal {

    @Override
    public void sound() {
        System.out.println("Cow moos");
    }
}

public class Deer implements Animal {

    @Override
    public void sound() {
        System.out.println("Deer grunts");
    }

}

public class Hyena implements Animal {

    @Override
    public void sound() {
        System.out.println("Hyena.java");
    }

}

public class Lion implements Animal {

    @Override
    public void sound() {
        System.out.println("Lion roars");
    }

}

public interface ZooFactory {
    Animal animal1();

    Animal animal2();
}

public class CarnivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Lion();
    }

    @Override
    public Animal animal2() {
        return new Hyena();
    }

}

public class HerbivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Cow();
    }

    @Override
    public Animal animal2() {
        return new Deer();
    }

}

public interface AnimalFactory {
    public Animal createAnimal();
}

public class CowAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Cow();
    }

}

public class DeerAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Deer();
    }

}

public class HyenaAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Hyena();
    }

}

public class LionAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Lion();
    }

}
雨夜星沙 2024-11-09 18:43:57

我的结论是:没有区别。为什么?因为我看不出有任何理由为工厂以外的对象配备工厂方法 - 否则就会违反责任分离原则。此外,我看不出具有单个工厂方法的工厂和具有多个工厂方法的工厂之间有什么区别:两者都会创建“相关对象的家族”,除非有人可以证明单个家族成员的家族不是一个家族。或者包含单个项目的集合不是集合。

My conclusion: there is no difference. Why? Because I cannot see any justification to equip objects other than factories with factory methods - otherwise you get a violation of the separation of responsibility principle. In addition, I cannot see any difference between a factory with a single factory method and a factory with multiple factory methods: both create "families of related objects" unless anyone can prove that a single-family-member family is not a family. Or a collection that contains a single item is not a collection.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文