工厂方法模式解析

工厂方法模式概述

工厂方法模式是设计模式中的一种创建型模式,由著名的四人帮(Gang Of Four,GoF)在其著作中提出。工厂方法模式的定义是:“定义一个用于创建对象的接口,但让子类决定要实例化的类。工厂方法让一个类推迟实例化到子类。”为了更清楚地理解这个定义,将通过本文的各个部分来逐步解析。

工厂方法模式的定义与示例

将继续使用第一部分中的例子,以便能够理解当应用程序增长时会出现哪些类型的问题,以及何时应该使用工厂方法模式(因为每种模式都有自己的位置、优势和限制)。

首先,定义了一个名为IFan的接口,它包含两个方法:

interface IFan { void SwitchOn(); void SwitchOff(); }

最初,公司打算只创建三种类型的风扇:台扇、吊扇和排风扇。所有风扇都将具有SwitchOn()和SwitchOff()方法,它们的实现可能会有所不同。让使用相同的类并实现IFan接口。

class TableFan : IFan {...} class CeilingFan : IFan {...} class ExhaustFan : IFan {...}

到目前为止,编写的代码与“简单工厂模式”示例中的代码相同。

当实现工厂方法模式时,需要遵循其设计,如下所示:

根据定义,“定义一个用于创建对象的接口...”,所以让定义一个接口,它将包含一个创建风扇的方法。在子类中实现这个方法将具有创建具体对象的逻辑。

interface IFanFactory { IFan CreateFan(); }

注意:使用了IFanFactory接口,但也可以改用抽象类。抽象类需要至少有一个未实现的抽象方法,该方法将在子类中实现以创建对象。

继续定义:“...让子类决定要实例化的类...”:让创建子类,这些子类将决定将使用哪个具体类来创建实例。为了创建三种类型的对象,即TableFan、CeilingFan和ExhaustFan,需要创建三种类型的工厂或IFanFactory的子类。这些三个工厂将实现IFanFactory接口。

class TableFanFactory : IFanFactory {...} class CeilingFanFactory : IFanFactory {...} class ExhaustFanFactory : IFanFactory {...}

继续定义:“...工厂方法让一个类推迟实例化到子类。”:在这里,IFan CreateFan()是一个工厂方法。在具体工厂(TableFanFactory等)中的CreateFan方法(即工厂方法)内部,指定将实例化哪个确切的类以创建风扇对象。因此,IFanFactory将其子类(即TableFanFactory、CeilingFanFactory和ExhaustFanFactory)推迟决策具体类。

以下是客户端实现的示例:

static void Main(string[] args) { IFanFactory fanFactory = new PropellerFanFactory(); // 使用工厂方法模式创建风扇 IFan fan = fanFactory.CreateFan(); // 使用创建的对象 fan.SwitchOn(); Console.ReadLine(); }

何时使用工厂方法模式

在上面的例子中,为了创建三种类型的对象(TableFan、CeilingFan和ExhaustFan),创建了三个工厂类,而在学习“简单工厂模式”时,只创建了一个工厂。这是因为遵循了工厂方法模式的规则。现在问题来了,为什么需要使用工厂方法模式,因为已经可以通过“简单工厂模式”实现相同的功能。

假设公司即将推出一种名为“PropellerFan”的新风扇。这是新的需求。使用工厂方法模式,不需要像在“简单工厂模式”中那样添加新的条件,而只需创建一个名为“PropellerFan”的新类,并使其继承IFan接口,就像为其他风扇所做的那样。

class PropellerFan : IFan {.....}

然后,将创建一个新的工厂名为PropellerFanFactory,并使其继承自IFanFactory。每当客户端想要创建PropellerFan类的实例时,只需创建PropellerFanFactory的实例,客户端就可以获得PropellerFan的实例。

工厂方法模式的优势

在上一节中,看到了工厂方法模式遵循开闭原则。当新需求到来时,不需要修改现有代码,而只需要创建一个额外的工厂。

与简单工厂模式相比,使用工厂方法模式编写单元测试用例更容易,因为不使用switch-case(或长if-else块)。

为了支持额外的产品,不需要修改现有代码,只需要添加一个新的工厂类,因此不需要重新运行现有的旧单元测试。

客户端调用CreateFan(工厂方法),而不知道如何以及实际创建的对象类型是什么。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485