工厂方法模式是GoF 23种经典创建型设计模式之一,核心价值在于解耦对象的创建与使用,通过抽象化设计满足“开闭原则”,让系统在不修改原有代码的前提下灵活扩展产品类型。本文将从模式核心结构入手,详解其工作原理,提供C#、Python、Golang、C++及纯C语言的落地实现,并分析优缺点与适用场景,帮助开发者快速掌握该模式的实际应用。
一、工厂方法模式的核心结构
工厂方法模式通过分层设计,将产品创建逻辑抽象化,核心包含4个角色,各角色职责清晰、分工明确,共同实现“创建与使用分离”的目标,具体结构如下:
1.1 核心角色定义
抽象产品(Abstract Product):定义产品的统一规范,描述产品的核心行为与属性,是所有具体产品的父类(或接口)。例如“电子设备”抽象类,定义“开机”“关机”等通用方法。
具体产品(Concrete Product):实现抽象产品的接口,是工厂方法模式的最终创建目标,与具体工厂一一对应。例如“手机”“电脑”,均继承自“电子设备”,并实现各自的开机、关机逻辑。
抽象工厂(Abstract Factory):定义创建产品的抽象接口(仅声明创建方法,不实现具体逻辑),是所有具体工厂的父类(或接口),负责约束具体工厂的行为。
具体工厂(Concrete Factory):继承或实现抽象工厂,重写创建产品的方法,负责具体产品的实例化,是连接抽象产品与具体产品的桥梁。
1.2 核心工作流程
- 客户端无需直接创建产品,仅需依赖抽象工厂;2. 客户端根据需求选择具体工厂;3. 具体工厂调用自身的创建方法,生成对应的具体产品;4. 客户端通过抽象产品接口使用产品,无需关注产品的具体实现细节。
这种流程设计的核心优势的是“扩展无侵入”——新增产品时,只需新增具体产品类和对应具体工厂类,无需修改抽象工厂、已有具体工厂及客户端代码,完美契合开闭原则。
二、多语言实现(统一场景:电子设备创建)
以下以“电子设备创建”为统一场景(抽象产品:电子设备;具体产品:手机、电脑;抽象工厂:电子设备工厂;具体工厂:手机工厂、电脑工厂),分别实现工厂方法模式,覆盖5种主流语言,兼顾语法特性与模式核心。
2.1 C# 实现(抽象类+继承)
C#作为强类型面向对象语言,通过抽象类+继承天然适配工厂方法模式,语法简洁且类型安全,适合企业级开发场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
| using System;
public abstract class ElectronicDevice { public abstract void PowerOn(); public abstract void PowerOff(); }
public class MobilePhone : ElectronicDevice { public override void PowerOn() { Console.WriteLine("手机开机,启动操作系统..."); }
public override void PowerOff() { Console.WriteLine("手机关机,保存数据..."); } }
public class Computer : ElectronicDevice { public override void PowerOn() { Console.WriteLine("电脑开机,加载驱动程序..."); }
public override void PowerOff() { Console.WriteLine("电脑关机,关闭后台进程..."); } }
public abstract class ElectronicDeviceFactory { public abstract ElectronicDevice CreateDevice(); }
public class MobilePhoneFactory : ElectronicDeviceFactory { public override ElectronicDevice CreateDevice() { Console.WriteLine("手机工厂:创建手机实例"); return new MobilePhone(); } }
public class ComputerFactory : ElectronicDeviceFactory { public override ElectronicDevice CreateDevice() { Console.WriteLine("电脑工厂:创建电脑实例"); return new Computer(); } }
class Client { static void Main(string[] args) { ElectronicDeviceFactory mobileFactory = new MobilePhoneFactory(); ElectronicDevice mobile = mobileFactory.CreateDevice(); mobile.PowerOn(); mobile.PowerOff();
ElectronicDeviceFactory computerFactory = new ComputerFactory(); ElectronicDevice computer = computerFactory.CreateDevice(); computer.PowerOn(); computer.PowerOff(); } }
|
2.2 Python 实现(abc模块+动态特性)
Python无严格的抽象类语法,通过abc模块实现抽象接口,结合动态语言的灵活性,简化工厂与产品的定义,代码简洁易读。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| from abc import ABC, abstractmethod
class ElectronicDevice(ABC): @abstractmethod def power_on(self): """抽象方法:开机""" pass
@abstractmethod def power_off(self): """抽象方法:关机""" pass
class MobilePhone(ElectronicDevice): def power_on(self): print("手机开机,启动操作系统...")
def power_off(self): print("手机关机,保存数据...")
class Computer(ElectronicDevice): def power_on(self): print("电脑开机,加载驱动程序...")
def power_off(self): print("电脑关机,关闭后台进程...")
class ElectronicDeviceFactory(ABC): @abstractmethod def create_device(self): """抽象创建方法""" pass
class MobilePhoneFactory(ElectronicDeviceFactory): def create_device(self): print("手机工厂:创建手机实例") return MobilePhone()
class ComputerFactory(ElectronicDeviceFactory): def create_device(self): print("电脑工厂:创建电脑实例") return Computer()
if __name__ == "__main__": mobile_factory = MobilePhoneFactory() mobile = mobile_factory.create_device() mobile.power_on() mobile.power_off()
computer_factory = ComputerFactory() computer = computer_factory.create_device() computer.power_on() computer.power_off()
|
2.3 Golang 实现(接口+结构体)
Golang无类继承特性,通过“接口+结构体”实现多态,核心是定义产品接口和工厂接口,结构体实现接口方法,贴合Go语言“面向接口编程”的设计理念。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| package main
import "fmt"
type ElectronicDevice interface { PowerOn() PowerOff() }
type MobilePhone struct{}
func (m *MobilePhone) PowerOn() { fmt.Println("手机开机,启动操作系统...") }
func (m *MobilePhone) PowerOff() { fmt.Println("手机关机,保存数据...") }
type Computer struct{}
func (c *Computer) PowerOn() { fmt.Println("电脑开机,加载驱动程序...") }
func (c *Computer) PowerOff() { fmt.Println("电脑关机,关闭后台进程...") }
type ElectronicDeviceFactory interface { CreateDevice() ElectronicDevice }
type MobilePhoneFactory struct{}
func (m *MobilePhoneFactory) CreateDevice() ElectronicDevice { fmt.Println("手机工厂:创建手机实例") return &MobilePhone{} }
type ComputerFactory struct{}
func (c *ComputerFactory) CreateDevice() ElectronicDevice { fmt.Println("电脑工厂:创建电脑实例") return &Computer{} }
func main() { var mobileFactory ElectronicDeviceFactory = &MobilePhoneFactory{} mobile := mobileFactory.CreateDevice() mobile.PowerOn() mobile.PowerOff()
var computerFactory ElectronicDeviceFactory = &ComputerFactory{} computer := computerFactory.CreateDevice() computer.PowerOn() computer.PowerOff() }
|
2.4 C++ 实现(纯虚函数+继承)
C++通过纯虚函数定义抽象接口(抽象产品、抽象工厂),结合继承实现具体产品与具体工厂,需注意虚析构函数的定义,避免内存泄漏,适合高性能、底层开发场景。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| #include <iostream> using namespace std;
class ElectronicDevice { public: virtual void PowerOn() = 0; virtual void PowerOff() = 0; virtual ~ElectronicDevice() {} };
class MobilePhone : public ElectronicDevice { public: void PowerOn() override { cout << "手机开机,启动操作系统..." << endl; }
void PowerOff() override { cout << "手机关机,保存数据..." << endl; } };
class Computer : public ElectronicDevice { public: void PowerOn() override { cout << "电脑开机,加载驱动程序..." << endl; }
void PowerOff() override { cout << "电脑关机,关闭后台进程..." << endl; } };
class ElectronicDeviceFactory { public: virtual ElectronicDevice* CreateDevice() = 0; virtual ~ElectronicDeviceFactory() {} };
class MobilePhoneFactory : public ElectronicDeviceFactory { public: ElectronicDevice* CreateDevice() override { cout << "手机工厂:创建手机实例" << endl; return new MobilePhone(); } };
class ComputerFactory : public ElectronicDeviceFactory { public: ElectronicDevice* CreateDevice() override { cout << "电脑工厂:创建电脑实例" << endl; return new Computer(); } };
int main() { ElectronicDeviceFactory* mobileFactory = new MobilePhoneFactory(); ElectronicDevice* mobile = mobileFactory->CreateDevice(); mobile->PowerOn(); mobile->PowerOff();
ElectronicDeviceFactory* computerFactory = new ComputerFactory(); ElectronicDevice* computer = computerFactory->CreateDevice(); computer->PowerOn(); computer->PowerOff();
delete mobile; delete mobileFactory; delete computer; delete computerFactory;
return 0; }
|
2.5 纯C语言实现(结构体+函数指针)
纯C语言无面向对象特性,通过“结构体嵌套+函数指针”模拟抽象接口与继承,核心是将产品行为、工厂创建逻辑封装为函数指针,实现类似多态的效果,适合底层嵌入式开发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <stdio.h> #include <stdlib.h>
typedef struct _ElectronicDevice { void (*PowerOn)(struct _ElectronicDevice*); void (*PowerOff)(struct _ElectronicDevice*); } ElectronicDevice;
typedef struct _MobilePhone { ElectronicDevice base; } MobilePhone;
void MobilePhone_PowerOn(ElectronicDevice* device) { printf("手机开机,启动操作系统...\n"); }
void MobilePhone_PowerOff(ElectronicDevice* device) { printf("手机关机,保存数据...\n"); }
typedef struct _Computer { ElectronicDevice base; } Computer;
void Computer_PowerOn(ElectronicDevice* device) { printf("电脑开机,加载驱动程序...\n"); }
void Computer_PowerOff(ElectronicDevice* device) { printf("电脑关机,关闭后台进程...\n"); }
typedef struct _ElectronicDeviceFactory { ElectronicDevice* (*CreateDevice)(struct _ElectronicDeviceFactory*); } ElectronicDeviceFactory;
typedef struct _MobilePhoneFactory { ElectronicDeviceFactory base; } MobilePhoneFactory;
ElectronicDevice* MobilePhoneFactory_CreateDevice(ElectronicDeviceFactory* factory) { printf("手机工厂:创建手机实例\n"); MobilePhone* mobile = (MobilePhone*)malloc(sizeof(MobilePhone)); mobile->base.PowerOn = MobilePhone_PowerOn; mobile->base.PowerOff = MobilePhone_PowerOff; return (ElectronicDevice*)mobile; }
typedef struct _ComputerFactory { ElectronicDeviceFactory base; } ComputerFactory;
ElectronicDevice* ComputerFactory_CreateDevice(ElectronicDeviceFactory* factory) { printf("电脑工厂:创建电脑实例\n"); Computer* computer = (Computer*)malloc(sizeof(Computer)); computer->base.PowerOn = Computer_PowerOn; computer->base.PowerOff = Computer_PowerOff; return (ElectronicDevice*)computer; }
int main() { MobilePhoneFactory mobileFactory; mobileFactory.base.CreateDevice = MobilePhoneFactory_CreateDevice; ElectronicDevice* mobile = mobileFactory.base.CreateDevice((ElectronicDeviceFactory*)&mobileFactory); mobile->PowerOn(mobile); mobile->PowerOff(mobile);
ComputerFactory computerFactory; computerFactory.base.CreateDevice = ComputerFactory_CreateDevice; ElectronicDevice* computer = computerFactory.base.CreateDevice((ElectronicDeviceFactory*)&computerFactory); computer->PowerOn(computer); computer->PowerOff(computer);
free(mobile); free(computer);
return 0; }
|
三、工厂方法模式的优缺点
工厂方法模式是在简单工厂模式基础上的优化,解决了简单工厂“扩展需修改代码”的核心问题,但同时也带来了一定的复杂度,需结合场景合理选择。
3.1 优点
符合开闭原则:新增产品时,仅需新增具体产品类和对应具体工厂类,无需修改原有抽象工厂、已有工厂及客户端代码,降低扩展成本。
解耦创建与使用:客户端仅依赖抽象工厂和抽象产品,无需了解产品的具体创建逻辑(如实例化细节、初始化步骤),降低代码耦合度。
支持多态扩展:通过抽象接口实现多态,具体工厂可灵活返回不同的具体产品,客户端无需修改代码即可使用新的产品。
责任单一:每个具体工厂仅负责创建一种具体产品,符合单一职责原则,便于代码维护和调试。
3.2 缺点
增加系统复杂度:每新增一个产品,需同时新增具体产品类和具体工厂类,导致系统类数量增多,增加代码量和维护成本。
层级冗余:相比简单工厂模式,多了抽象工厂和具体工厂的分层,对于简单场景(产品类型极少、无需扩展),显得过于繁琐。
理解成本提升:需理解抽象接口、多态等概念,对于新手而言,上手难度高于简单工厂模式。
四、工厂方法模式的使用场景
工厂方法模式适合“产品类型需灵活扩展、需隐藏创建细节”的场景,具体应用如下:
产品类型稳定且需扩展:如电商系统的支付方式(支付宝、微信支付、银行卡支付),新增支付方式时,仅需新增支付产品类和支付工厂类,无需修改原有支付逻辑。
隐藏产品创建细节:如数据库连接池、日志管理器,客户端无需关心连接/日志实例的创建、初始化、销毁细节,仅通过工厂获取实例即可。
框架/库设计:框架开发中,为了让用户能扩展自定义产品,通常会提供抽象工厂接口,用户通过实现具体工厂和产品,集成到框架中(如.NET的HandlerFactory、Spring的BeanFactory)。
多环境适配:如不同环境(开发、测试、生产)的配置实例创建,通过不同的具体工厂,返回适配对应环境的配置产品,客户端无需修改代码即可切换环境。
注意:若产品类型极少(如仅1-2种)且无需扩展,建议使用简单工厂模式;若需支持多系列产品(如手机+电脑+平板,每种产品又有不同品牌),建议使用抽象工厂模式。
五、总结
工厂方法模式的核心是“抽象化创建逻辑,通过多态实现扩展”,其本质是将对象创建的责任委托给具体工厂,实现“创建与使用分离”,核心价值在于满足开闭原则,提升系统的灵活性和可维护性。
从多语言实现来看,尽管不同语言的语法差异显著,但核心思想完全一致:
在实际开发中,选择工厂方法模式的关键的是“判断产品是否需要扩展”:若产品固定不变,简单工厂模式更简洁;若产品需灵活扩展,工厂方法模式是更优选择。同时,需权衡系统复杂度与扩展性,避免过度设计——无需为了使用设计模式而强行引入分层,适合的场景才是最好的。