C#工厂方法模式(Factory Method)详解与应用

内容分享7小时前发布
0 0 0

一、工厂方法模式核心定义

工厂方法模式(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 种)且永不扩展,无需使用工厂方法,简单工厂更合适。

© 版权声明

相关文章

暂无评论

none
暂无评论...