一、工厂方法模式核心定义
工厂方法模式(Factory Method)是创建型设计模式,核心目标是:
定义一个创建对象的抽象接口(工厂接口 / 抽象类),将对象的实例化延迟到其子类;解耦 “对象的创建” 和 “对象的使用”,让客户端只依赖抽象,不依赖具体产品;支持产品类型的扩展,新增产品时无需修改原有代码(符合开闭原则)。
二、工厂方法模式的核心结构
工厂方法模式包含 4 个核心角色,我用表格清晰梳理:
| 角色名称 | 作用 |
|---|---|
| 抽象产品(Product) | 定义产品的公共接口 / 抽象类,规定所有具体产品必须实现的方法 |
| 具体产品(Concrete Product) | 实现抽象产品接口,是工厂方法创建的目标对象 |
| 抽象工厂(Creator) | 定义工厂方法的抽象接口 / 抽象类,返回抽象产品类型,不负责具体实例化 |
| 具体工厂(Concrete Creator) | 实现抽象工厂的工厂方法,返回具体产品的实例(真正创建对象的地方) |
三、C# 完整实现示例(电商支付场景)
以电商系统的 “支付方式” 为例(支持支付宝、微信支付,后续可扩展银联支付),这是工厂方法模式最典型的应用场景:
步骤 1:定义抽象产品(支付方式接口)
/// <summary>
/// 抽象产品:支付方式接口(定义所有支付方式的公共行为)
/// </summary>
public interface IPayment
{
/// <summary>
/// 执行支付
/// </summary>
/// <param name="amount">支付金额</param>
/// <returns>支付结果</returns>
string Pay(decimal amount);
}
步骤 2:实现具体产品(支付宝 / 微信支付)
/// <summary>
/// 具体产品:支付宝支付
/// </summary>
public class AlipayPayment : IPayment
{
public string Pay(decimal amount)
{
// 模拟支付宝支付逻辑
return $"支付宝支付成功,金额:{amount:C},交易号:{Guid.NewGuid()}";
}
}
/// <summary>
/// 具体产品:微信支付
/// </summary>
public class WechatPayment : IPayment
{
public string Pay(decimal amount)
{
// 模拟微信支付逻辑
return $"微信支付成功,金额:{amount:C},交易号:{Guid.NewGuid()}";
}
}
步骤 3:定义抽象工厂(支付工厂接口)
/// <summary>
/// 抽象工厂:支付工厂接口(定义创建支付方式的工厂方法)
/// </summary>
public interface IPaymentFactory
{
/// <summary>
/// 工厂方法:创建支付方式实例
/// </summary>
/// <returns>具体的支付方式实例</returns>
IPayment CreatePayment();
}
步骤 4:实现具体工厂(支付宝 / 微信支付工厂)
/// <summary>
/// 具体工厂:支付宝支付工厂(负责创建支付宝支付实例)
/// </summary>
public class AlipayFactory : IPaymentFactory
{
public IPayment CreatePayment()
{
// 可在这里添加支付宝支付的初始化逻辑(如读取配置、初始化SDK)
return new AlipayPayment();
}
}
/// <summary>
/// 具体工厂:微信支付工厂(负责创建微信支付实例)
/// </summary>
public class WechatFactory : IPaymentFactory
{
public IPayment CreatePayment()
{
// 可在这里添加微信支付的初始化逻辑(如读取appid、密钥)
return new WechatPayment();
}
}
步骤 5:客户端调用(使用工厂创建产品)
class Program
{
static void Main(string[] args)
{
// 1. 选择支付方式(可从配置/用户输入获取)
string paymentType = "Alipay"; // 可改为"Wechat"测试
// 2. 创建对应的工厂
IPaymentFactory factory = paymentType switch
{
"Alipay" => new AlipayFactory(),
"Wechat" => new WechatFactory(),
_ => throw new NotSupportedException("不支持的支付方式")
};
// 3. 通过工厂创建支付实例
IPayment payment = factory.CreatePayment();
// 4. 执行支付(客户端只依赖抽象,不依赖具体产品)
string result = payment.Pay(199.99m);
Console.WriteLine(result);
// 输出示例(支付宝):
// 支付宝支付成功,金额:¥199.99,交易号:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
}
}
扩展新产品(银联支付)
如果后续需要支持银联支付,无需修改任何原有代码,只需新增两个类:
// 1. 新增具体产品:银联支付
public class UnionPayPayment : IPayment
{
public string Pay(decimal amount)
{
return $"银联支付成功,金额:{amount:C},交易号:{Guid.NewGuid()}";
}
}
// 2. 新增具体工厂:银联支付工厂
public class UnionPayFactory : IPaymentFactory
{
public IPayment CreatePayment()
{
return new UnionPayPayment();
}
}
// 客户端调用时只需新增一个分支
// IPaymentFactory factory = paymentType switch
// {
// "Alipay" => new AlipayFactory(),
// "Wechat" => new WechatFactory(),
// "UnionPay" => new UnionPayFactory(), // 新增
// _ => throw new NotSupportedException("不支持的支付方式")
// };
四、工厂方法模式 vs 简单工厂模式(关键区别)
很多新手会混淆这两种模式,我用表格对比核心差异,帮你区分:
| 特性 | 工厂方法模式 | 简单工厂模式 |
|---|---|---|
| 结构 | 抽象工厂 + 多个具体工厂 | 一个工厂类(包含所有产品的创建逻辑) |
| 开闭原则 | 符合(新增产品只需加工厂,不修改原有) | 不符合(新增产品需修改工厂的 if/switch) |
| 复杂度 | 稍高(需定义多个工厂类) | 简单(仅一个工厂类) |
| 适用场景 | 产品类型多、需频繁扩展 | 产品类型少、稳定不扩展 |
五、工厂方法模式的优缺点
优点
符合开闭原则:新增产品时只需新增 “具体产品 + 具体工厂”,无需修改原有代码;解耦创建与使用:客户端只依赖抽象(IPayment/IPaymentFactory),不依赖具体实现,降低耦合;单一职责原则:每个具体工厂只负责创建对应的产品,职责单一,代码易维护;扩展性强:产品类型可无限扩展,且扩展成本低。
缺点
类数量膨胀:每新增一个产品,就需要新增 “具体产品类 + 具体工厂类”,增加类的数量;复杂度提升:相比简单工厂,多了抽象工厂和多个具体工厂,入门门槛稍高;适用场景有限:如果产品类型极少且稳定,使用工厂方法会过度设计。
六、工厂方法模式的实际应用场景
场景 1:日志框架(文件日志 / 数据库日志 / 控制台日志)
抽象产品:ILogger(定义 WriteLog 方法);具体产品:FileLogger、DbLogger、ConsoleLogger;具体工厂:FileLoggerFactory、DbLoggerFactory、ConsoleLoggerFactory;优势:新增 “Elasticsearch 日志” 时,只需加 ElasticsearchLogger 和对应的工厂,不改动原有代码。
场景 2:数据导出(Excel/CSV/PDF 导出)
抽象产品:IExporter(定义 Export 方法);具体产品:ExcelExporter、CsvExporter、PdfExporter;具体工厂:ExcelExporterFactory、CsvExporterFactory、PdfExporterFactory;优势:客户端只需选择工厂,无需关心不同格式的导出细节。
场景 3:图形绘制(圆形 / 矩形 / 三角形)
抽象产品:IShape(定义 Draw 方法);具体产品:Circle、Rectangle、Triangle;具体工厂:CircleFactory、RectangleFactory、TriangleFactory;优势:新增 “五角星” 图形时,只需扩展,不影响现有绘制逻辑。
总结
核心逻辑:工厂方法模式通过 “抽象工厂 + 具体工厂” 将对象创建延迟到子类,核心是抽象解耦 + 开闭原则;使用原则:产品类型多、需频繁扩展时用工厂方法,产品少且稳定时用简单工厂;关键优势:新增产品无需修改原有代码,符合开闭原则,是应对 “产品扩展” 的最优创建模式之一;避坑点:避免过度设计 —— 如果产品类型极少(如仅 2 种)且永不扩展,无需使用工厂方法,简单工厂更合适。





