工厂模式 - 抽象工厂模式






4.94/5 (30投票s)
在本文中,我们将理解抽象工厂模式。本文是工厂模式文章系列的第三部分,是第一部分(简单工厂模式)和第二部分(工厂方法模式)的延续。
引言
在本文中,我们将理解抽象工厂模式。本文是工厂模式文章系列的第三部分,是第一部分(简单工厂模式)和第二部分(工厂方法模式)的延续。在第一部分中,我们学习了简单工厂模式,在第二部分中,我们学习了工厂方法模式,现在轮到抽象工厂模式了。如果您还没有看过第一部分和第二部分,我建议您先阅读它们,然后再继续阅读本文。
目录
第一部分 - 简单工厂模式
第二部分 - 工厂方法模式
第三部分 - 抽象工厂模式
- 什么是抽象工厂模式
- 何时使用抽象工厂模式
- 通过示例理解定义
- 抽象工厂模式的问题
什么是抽象工厂模式
抽象工厂模式是《设计模式》(Gang of Four, GoF)一书的一部分,属于创建型模式。以下是从《设计模式》(GoF)一书中摘录的抽象工厂模式的定义:
“为创建相关或依赖对象的系列提供一个接口,而无需指定它们的具体类。”
我们将在本文的“通过示例理解定义”部分详细讲解这个定义。
何时使用抽象工厂模式
当我们想创建不同种类的相关对象(属于一个组/集合)时,抽象工厂模式是一个选择。它提供了不同种类的工厂。每个工厂将创建一个特定种类的相关对象。因此,有时我们称抽象工厂模式为工厂的工厂。简单工厂模式和工厂方法模式只提供一种对象(在我们的示例中,所有对象都属于IFan类型)。
注意:抽象工厂模式如果需要,可以与工厂方法模式一起使用。
现在,除了风扇,如果我们还需要创建更多的电器设备,比如日光灯或开关,那么我们将选择抽象工厂。为了更清楚地说明,让我们扩展一下场景,在这个场景中,我们需要创建属于一组(电器设备组)的不同种类的相关对象。我们将继续使用在本系列文章第二部分中使用的类似示例。
现在让我们理解扩展场景:有一家电器公司,生产各种电器设备,如风扇和日光灯。目前该公司只在印度,称为印度电器公司。现在,同一家公司希望在美国设立一个新的分支机构,名为美国电器公司,该公司将按照美国标准制造称为风扇和日光灯的电器设备。所以这里我们有两种电器设备组——称为印度电器设备和美国电器设备。这些组中的相关对象是风扇和日光灯(可能还有更多这样的电器设备)。
通过示例理解定义
让我们借助上述场景来理解抽象工厂模式的定义。首先创建上述场景的设计图,并尝试将定义与该场景关联起来。下图显示了实现上述场景所需的实体。
在上图中,IElectricalFactory为客户端提供了**创建相关或依赖对象族的接口**。这里我们有两个该接口的具体实现——IndianElectricalFactory和USElectricalFactory类。这两个类生产**两种不同类型的相关对象族——风扇和日光灯**。IndianFan和IndianTubelight属于IndianElectricalFactory族。USTubelight和USFan类属于USElectricalFactory族。
抽象工厂模式的主要组成部分/参与者
- 抽象工厂(IElectricalFactory)
- 具体工厂(IndianElectricalFactory, USElectricalFactory)
- 抽象产品(IFan, ITubeLight)
- 具体产品(IndianFan, IndianTubelight, USFan, USTubelight)
以下是上述场景的逐步实现
创建两个名为IFan和ITubelight的接口。
interface IFan { void SwithOn(); } interface ITubelight { }
创建两个具体类,如下所示,通过实现IFan和ITubelight。接口的实现将根据印度电器设备标准。
class IndianFan : IFan { } class IndianTubelight : ITubelight { }
创建一个IElectricalFactory接口,这个接口是实际的抽象工厂,它将创建相关对象族。
interface IElectricalFactory { IFan GetFan(); ITubelight GetTubeLight(); }
创建一个IndianElecticalFactory类,并从IElectricalFactory接口继承它。它将实现GetFan和GetTubeLight两个方法。GetFan返回IndianFan类的对象,因为IndianFan类实现了IFan接口。类似地,GetTubeLight将返回IndianTubelight类的对象。
class IndianElectricalFactory : IElectricalFactory { public IFan GetFan() { return new IndianFan(); } public ITubelight GetTubeLight() { return new IndianTubelight(); } }
到目前为止,IndianElecticalFactory类已经准备好创建IndianFan和IndianTubelight。现在我们来看看客户端如何创建它们。
static void Main(string[] args) { IElectricalFactory electricalFactory = new IndianElectricalFactory(); IFan fan = electricalFactory.GetFan(); fan.SwithOn(); Console.ReadKey(); }
如上文所述,公司希望在美国设立新的电器公司,公司名称为USElectricalFactory。在同一个应用程序中,我们将添加两个新类,称为USFan和USTubelight,通过实现所需的接口。这里的IFan和ITubeLight接口的实现将根据美国电器设备标准。
class USFan : IFan { } class USTubelight : ITubelight { }
最后创建USElectricalFactory类,它也继承自IElectricalFactory。
class USElectricalFactory : IElectricalFactory { public IFan GetFan() { return new USFan(); } public ITubelight GetTubeLight() { return new USTubelight(); } }
现在,如果客户端想获取美国电器设备,只需更改客户端代码中的一个地方即可,如下所示:
//IElectricalFactory electricalFactory = new IndianElectricalFactory(); IElectricalFactory electricalFactory = new USElectricalFactory();
抽象工厂模式的问题
唯一可能出现的问题是如果我们更改了抽象工厂本身提供的接口。这种情况很少见,并且所有遵循“对接口编程,而不是对实现编程”设计理念的程序都会遇到这个问题。同一个问题在此StackOverflow页面进行了讨论。在我们的例子中,如果IElectricalFactory接口发生任何更改,所有工厂都需要更改。
结论
在本文中,我们通过一个演练来学习抽象工厂模式及其用法。我们理解了抽象工厂模式的上下文以及如何使用它来提高应用程序的可维护性。感谢阅读。欢迎提出您的评论和改进建议。