为什么我们需要抽象工厂设计模式?

Why do we need Abstract factory design pattern?

大多数定义都说:

An abstract factory provides an
interface for creating families of
related objects without specifying
their concrete classes

抽象工厂模式的用途是什么,因为我们可以通过创建具体类本身的对象来完成任务。为什么我们有一个工厂方法来创建具体类的对象?

请提供任何我必须实现AbstractFactory模式的实际示例?


抽象工厂是依赖注入(DI)的一个非常中心的设计模式。下面是一个堆栈溢出问题列表,其中抽象工厂的应用程序已被接受为解决方案。

据我所知,这些问题代表了人们真正关心的问题,所以你应该从一些现实生活的例子开始:

  • 有没有初始化通过DI容器创建的对象的模式?
  • 无法合并工厂/DI
  • WCF依赖项注入和抽象工厂
  • 当关键类需要会话(或其他上下文特定变量)时如何设置IOC
  • 如何根据最终用户配置值解析类型?
  • 使用Unity的策略模式和依赖注入
  • 在IOC上抽象工厂模式?
  • 这是使用和测试使用工厂模式的类的正确方法吗?
  • DDD书籍,埃里克·埃文斯:请解释"工厂应该抽象为所需的类型,而不是创建的具体类"的含义。
  • DI容器、工厂或临时物品的新容器?
  • 如何创建单元测试实例?
  • 什么是用户输入依赖项注入的最佳策略?


使用抽象工厂模式的现实例子是提供对两个不同数据源(如SQL数据库和XML文件)的数据访问。您有两个不同的数据访问类(数据存储的网关)。两者都继承自定义要实现的公共方法(例如,加载、保存、删除)的基类。

应使用哪个数据源不应改变客户端代码检索其数据访问类的方式。您的抽象工厂知道应该使用哪个数据源,并根据请求返回适当的实例。工厂将此实例作为基类类型返回。


如果我对你的理解是正确的-问题是,为什么我们有工厂方法和抽象的工厂模式。当不同的多态类具有不同的实例化过程时,需要使用抽象工厂。您希望一些模块创建实例并使用它们,而不知道对象初始化的任何细节。例如,您要创建Java对象,进行一些计算。但其中一些是应用程序的一部分,而另一些字节码应该从数据库中读取。另一方面,为什么我们需要工厂方法?同意,抽象工厂与之重叠。但在某些情况下——编写代码要少得多,类和接口更少,这使得系统更容易理解。


What is the use of Abstract Factory Pattern as we can achieve the task via creating object of concrete class itself. Why do we have a factory method that creates object of Concrete class?

在没有抽象工厂的情况下,客户需要知道具体类的细节。这个紧耦合已与抽象工厂一起拆下。

现在工厂方法公开了一个契约,客户机必须使用它。您可以通过添加新产品向工厂添加更多产品,这些新产品实现了工厂方法公开的接口。

请参考这些相关的SE问题以更好地理解:

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

意图:

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

您可以从本文中了解抽象工厂模式的意图、结构、清单和经验法则。

清单:

  • 决定平台独立性和创建服务是否是当前的痛苦来源。
  • 绘制平台与产品之间的矩阵。
  • 定义由每个产品的工厂方法组成的工厂接口。
  • 为每个平台定义一个工厂派生类,该类封装对新运算符的所有引用。
  • 客户机应该注销对new的所有引用,并使用工厂方法来创建产品对象。

  • 抽象工厂非常适合在保持代码库统一的同时支持多个平台。假设您有一个大型的qt或gtk+或.net/mono程序,希望在Windows、Linux和OSX上运行。但是,您有一个在每个平台上以不同的方式实现的特性(可能通过Kernel32 API或POSIX特性实现)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public abstract class Feature
    {
        public abstract int PlatformSpecificValue { get; }

        public static Feature PlatformFeature
        {
            get
            {
                string platform;
                // do platform detection here
                if (platform =="Win32")
                    return new Win32Feature();
                if (platform =="POSIX")
                    return new POSIXFeature();
            }
        }

        // platform overrides omitted
    }

    使用这个抽象工厂,您的用户界面不需要了解任何关于当前平台的信息。

    1
    2
    Feature feature = Feature.PlatformFeature;
    Console.WriteLine(feature.PlatformSpecificValue);


    我认为在你的实例非常复杂的地方有一个抽象工厂模式的地方,而不是简单工厂模式的地方,对于一个工厂来说过于复杂和丑陋,对于用户界面来说过于复杂。

    假设这是一个"A"型品牌,而不是一个档次。假设有一个包含100种类型A类似类的家族,您需要从中实例化一个对象。假设有一个细节复杂的信息需要使正确的对象从一个品牌的许多类似类型的对象,在这个对象实体中,你需要确切地知道哪些参数,如何调整它们。

    在这个品牌的特殊工厂里,我们会让他们区分并得到精确的对象来实例化,以及如何实例化它。我们将知道,根据网络的输入(假设在线商店中有什么颜色),以及在后台运行的其他应用程序和服务(用户界面不知道这些参数)。

    也许明天我们会有另一个家族,比如说B型和C型。因此,用户界面将有"if else"来知道用户是否需要"type_a"、"type_b"或"type_c"—但是工厂类将精确地决定要构建的类型(来自系列)中的哪个类,以及如何对其进行调优—要为其参数设置什么值,或发送给其承包商。所有这些-根据用户界面不知道的许多参数。所有这些对于一个工厂类来说都太多了。


    很容易,想象一下您有一个代码可以处理抽象,您应该创建抽象,而不是具体的类。

    您应该始终反对抽象,因为您可以更好地修改代码。

    这是一个很好的例子:http://en.wikipedia.org/wiki/abstract_工厂模式


    如果你看一下设计模式,几乎所有的模式都是多余的。但是,什么模式意味着解决类似类型问题的常用方法。设计模式为您提供了一种设计级别的方法或解决方案,以解决一组类似类型的设计问题。使用设计模式可以帮助您解决问题,从而更快地交付。


    This pattern is particularly useful when the client doesn't know
    exactly what type to create. As an example, let's say a Showroom
    exclusively selling cellphones gets a query for the smart phones made
    by Samsung. Here we don't know the exact type of object to be created
    (assuming all the information for a phone is wrapped in the form of a
    concrete object). But we do know that we are looking for smart phones
    that are manufactured by Samsung. This information can actually be
    utilized if our design has Abstract factory implementation.

    在C语言中理解和实现抽象工厂模式#


    假设您创建了一个.jar,其他人使用您的jar并希望在代码中使用一个新的具体对象。如果您不使用抽象工厂,那么她必须修改您的代码或覆盖您的代码。但是如果您使用的是抽象工厂,那么她可以提供一个工厂并传递给您的代码,一切都很好。

    精致版:考虑以下情况:其他人编写了一个框架。框架使用抽象工厂和一些具体工厂在运行时创建大量对象。因此,您可以轻松地将自己的工厂注册到现有框架并创建自己的对象。由于抽象的工厂模式,框架不允许修改,而且仍然易于扩展。


    一切都与依赖有关。如果您不关心紧密耦合和依赖性,那么就不需要一个抽象工厂。但一旦你写了一个需要维护的应用程序,它就会很重要。


    要直接回答您的问题,您可能不需要使用这种设计模式就可以离开。

    但是请记住,现实世界中的大多数项目都在发展,您希望提供某种可扩展性,以便使您的项目成为未来的证据。

    根据我自己的经验,大多数情况下,工厂是被实现的,随着项目的发展,它会变成更复杂的设计模式,比如抽象工厂。


    我发现抽象的工厂模式被高估了。

    首先,如果您有一组要实例化的相互关联的类型,则不会经常发生这种情况。

    其次,当处理依赖注入时,接口提供的间接(抽象)级别通常足够。

    windowsgui与macgui与…如果你有一个windowsbutton、macbutton、windowsscrollbar、macscrollbar等,那么通过定义具体的按钮、滚动条等,使用访问者和/或解释器模式来提供实际的行为,通常更容易实现。