ChatGPT解决这个技术问题 Extra ChatGPT

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

大多数定义说:

抽象工厂为创建相关对象族提供了一个接口,而无需指定它们的具体类

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

请提供我必须实现 abstractFactory 模式的任何现实生活示例?


C
Community

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

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

是否有用于初始化通过 DI 容器创建的对象的模式

无法结合 Factory / DI

WCF依赖注入和抽象工厂

当关键类需要 Session(或其他特定于上下文的变量)时如何设置 IoC

如何根据最终用户配置值解析类型?

使用 Unity 的策略模式和依赖注入

IoC 之上的抽象工厂模式?

这是使用和测试使用工厂模式的类的正确方法吗?

DDD Book,Eric Evans:请解释“工厂应该抽象为所需的类型,而不是创建的具体类”是什么意思。

DI 容器、工厂或临时对象的新容器?

如何单元测试实例创建?

用户输入依赖注入的最佳策略是什么?


所有这些示例都描述了工厂方法模式,因为它们都返回单个产品接口。这些都不是抽象工厂模式,因为它们都没有产生一系列相关的产品接口。
为了充分披露,该答案的作者应该明确表示他也是每个链接答案的作者;所以这个列表不是来自 SO 社区的代表性样本。
@jaco0646 IIRC,Factory Method patternTemplate Method pattern 的一个特化,它依赖于继承。不过,我可能弄错了,因为我目前正在旅行,并且没有随身携带我的 GoF 书。 “他们都没有生产一系列相关的产品接口”是什么意思?
表明工厂不符合抽象工厂模式的最简单线索是计算工厂生产的抽象产品(我使用术语“产品接口”代替“抽象产品”以避免过度使用“抽象”一词) .生产单一抽象产品的工厂不能是抽象工厂,因为根据定义,抽象工厂生产一系列相关产品。重要的是要注意这个系列并不是指一个接口的不同实现,而是指具有不同相关接口的产品。
这是一个示例 oodesign.com/abstract-factory-pattern.html。这就是最初创建抽象工厂模式的目的。
J
Johannes Rudolph

使用抽象工厂模式的一个真实示例是提供对两个不同数据源的数据访问。假设您的应用程序支持不同的数据存储。 (例如,一个 SQL 数据库和一个 XML 文件)。您有两个不同的数据访问接口,例如 IReadableStoreIWritableStore,它们定义了您的应用程序期望的常用方法,而不管使用的数据源类型如何。

应使用哪种类型的数据源不应改变客户端代码检索其数据访问类的方式。您的 AbstractDataAccessFactory 知道配置了哪种类型的数据源,并为客户端代码(即 SqlDataAccessFactoryXmlDataAccessFactory)提供了一个具体工厂。这些具体工厂可以创建具体的实现,例如SqlReadableStoreSqlWriteableStore

.NET Framework 中的 DbProviderFactory 就是这种模式的一个示例。


这个答案可以准确地描述工厂方法模式或静态工厂模式,但不能准确描述抽象工厂模式。
D
David Gruzman

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


p
piedar

抽象工厂非常适合支持多个平台,同时保持代码库的统一。假设您有一个想要在 Windows、Linux 和 OSX 上运行的大型 Qt 或 GTK+ 或 .NET/Mono 程序。但是您有一个功能在每个平台上以不同的方式实现(可能通过 kernel32 API 或 POSIX 功能)。

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
}

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

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

我不明白,这与仅使用工厂方法返回抽象类型以使客户端不知道实现细节有什么不同?
E
EnterTheCode

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

在没有抽象工厂的情况下,客户需要知道具体类的细节。抽象工厂已经移除了这种紧密耦合。

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

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

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

意图:

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

您可以通过这篇sourcemaking文章了解抽象工厂模式的意图、结构、清单和经验法则

清单:

确定平台独立性和创建服务是否是当前的痛点。绘制出平台与产品的矩阵。定义一个由每个产品的工厂方法组成的工厂接口。为每个平台定义一个工厂派生类,该类封装了对 new 运算符的所有引用。客户端应该取消对 new 的所有引用,并使用工厂方法创建产品对象。


P
Pablo Castilla

很容易,想象你有一个与抽象一起工作的代码,你应该创建抽象而不是具体的类。

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

这是一个很好的例子:http://en.wikipedia.org/wiki/Abstract_factory_pattern#C.23


K
Kangkan

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


e
eljenso

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

首先,您想要实例化一组相互关联的类型并不经常发生。

其次,接口提供的间接(抽象)级别通常在使用依赖注入时就足够了。

WindowsGui vs MacGui vs ...的典型示例,您将拥有WindowsButton、MacButton、WindowsScrollBar、MacScrollbar等,通常通过使用访问者和/或解释器模式定义具体按钮、滚动条等更容易实现实际行为。


有一个特定的目的。使用依赖注入,您不希望服务定位器远离复合根。相反,您使用注入的抽象工厂。
好吧...使用带有 DI 的服务定位器是一种反模式。当我们需要从运行时值创建依赖项时,抽象工厂是通用的解决方案。
A
Amir Shabani

当客户端不确切知道要创建什么类型时,此模式特别有用。例如,假设专门销售手机的 Showroom 查询三星制造的智能手机。在这里,我们不知道要创建的对象的确切类型(假设电话的所有信息都以具体对象的形式包装)。但我们确实知道我们正在寻找三星制造的智能手机。如果我们的设计具有抽象工厂实现,则实际上可以使用此信息。

Understanding and Implementing Abstract Factory Pattern in C#


U
Udi Reshef

我认为在您的实例化非常复杂、对于单个工厂而言过于复杂和丑陋并且对于 UI 无法理解的情况而言过于复杂的地方,存在抽象工厂模式而不是简单工厂模式的地方。

假设这是一个 TYPE_A 品牌,而不是单个类。假设有 100 种相似的 Type-A 类,您需要从中实例化一个对象。想象一下,为了从许多相似类型的对象中制作正确的对象,需要详细的复杂信息,并且在这个对象实体中,您需要准确地知道要调整哪些参数以及如何调整它们。

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

也许明天我们会有另一个系列,比如说 type_B 和 type_C 来实例化。因此,UI 将通过“if else”来了解用户是否想要“type_A”、“type_B”或“type_C”——但工厂类将准确地决定要构建类型(来自家族)中的哪个类,并且如何调整它——为它的参数设置什么值,或者发送给它的承包商。所有这一切 - 根据 UI 不知道的许多参数。对于单个工厂类来说,所有这些都太过分了。


U
Uday Reddy

抽象工厂或任何工厂,它们的存在是为了解决相同的问题,即“对象创建的抽象”。

它通常抽象出以下内容:

if 条件来决定实例化哪个对象。 new 运算符,对象的实例化。

简而言之,工厂的责任就是这样。

您可以通过 this 了解详细说明。


B
BlueTrin

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

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

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


D
Daniel B

这都是关于依赖关系的。如果您不关心紧密耦合和依赖关系,那么您不需要抽象工厂。但是,一旦您编写了需要维护的应用程序,它就会很重要。


A
Adrian Liu

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

精炼版:考虑下面的场景:别人写了一个框架。该框架使用抽象工厂和一些具体工厂在运行时创建大量对象。因此,您可以轻松地将自己的工厂注册到现有框架并创建自己的对象。由于抽象工厂模式,该框架对修改是封闭的,并且仍然易于扩展。