01. 工厂模式(Factory Pattern)

01. 工厂模式(Factory Pattern)

分类 : 创建型模式

热门度 : ★★★★★

难度: ★★☆☆☆


📖 概念

工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,而不必暴露创建逻辑给客户端。通过使用一个共同的接口来指向新创建的对象,将对象的实例化延迟到子类或工厂类中。

工厂模式包含三种形式:简单工厂 、工厂方法 和抽象工厂(抽象工厂单独作为模式02讲解)。

🎯 意图

定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类,从而实现创建者与具体产品之间的解耦。

🔑 关键角色

角色 说明
抽象产品(Product) 定义产品对象的通用接口,所有具体产品都实现此接口
具体产品(Concrete Product) 实现抽象产品接口的具体类
工厂(Factory) 负责创建具体产品实例的类或方法
客户端(Client) 使用工厂来获取产品实例,不直接实例化具体产品

⚠️ 注意事项

  • 简单工厂违反开闭原则,每次新增产品都需要修改工厂类
  • 工厂方法模式通过继承来创建对象,抽象工厂通过组合来创建对象族
  • 避免工厂类过于复杂,如果产品类型过多,考虑使用注册表或反射机制
  • 工厂模式会增加系统中类的数量,需要权衡复杂度

🔄 实现流程

复制代码
客户端 → 调用工厂方法并传入参数
        → 工厂根据参数判断应创建哪个具体产品
        → 实例化具体产品对象
        → 返回抽象产品类型给客户端
        → 客户端通过统一接口使用产品

💡 常见使用场景

场景1: 日志系统(Logger System)

根据配置创建不同类型的日志记录器(文件日志、数据库日志、控制台日志),客户端无需关心具体实现。

csharp 复制代码
using System;

// 抽象产品
public interface ILogger
{
    void Log(string message);
}

// 具体产品 - 文件日志
public class FileLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[FILE] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
    }
}

// 具体产品 - 数据库日志
public class DatabaseLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[DB] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
    }
}

// 具体产品 - 控制台日志
public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine($"[CONSOLE] {DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}");
    }
}

// 工厂
public static class LoggerFactory
{
    public static ILogger CreateLogger(string type)
    {
        return type.ToLower() switch
        {
            "file" => new FileLogger(),
            "database" or "db" => new DatabaseLogger(),
            "console" => new ConsoleLogger(),
            _ => throw new ArgumentException($"Unknown logger type: {type}")
        };
    }
}

// 客户端调用
public class Program
{
    public static void Main()
    {
        ILogger logger = LoggerFactory.CreateLogger("file");
        logger.Log("Application started");
    }
}

场景2: 数据库连接工厂(Database Connection Factory)

根据不同的数据库类型创建对应的连接对象,统一管理数据库连接的创建。

csharp 复制代码
using System;

// 抽象产品(避免与 System.Data.IDbConnection 冲突,加自定义前缀)
public interface IMyDbConnection
{
    void Open();
    void Close();
    string ConnectionString { get; }
}

// 具体产品 - SQL Server
public class SqlServerConnection : IMyDbConnection
{
    public string ConnectionString { get; private set; }

    public SqlServerConnection(string connectionString)
    {
        ConnectionString = connectionString;
    }

    public void Open() => Console.WriteLine("SQL Server connection opened.");
    public void Close() => Console.WriteLine("SQL Server connection closed.");
}

// 具体产品 - MySQL
public class MySqlConnection : IMyDbConnection
{
    public string ConnectionString { get; private set; }

    public MySqlConnection(string connectionString)
    {
        ConnectionString = connectionString;
    }

    public void Open() => Console.WriteLine("MySQL connection opened.");
    public void Close() => Console.WriteLine("MySQL connection closed.");
}

// 具体产品 - PostgreSQL
public class PostgreSqlConnection : IMyDbConnection
{
    public string ConnectionString { get; private set; }

    public PostgreSqlConnection(string connectionString)
    {
        ConnectionString = connectionString;
    }

    public void Open() => Console.WriteLine("PostgreSQL connection opened.");
    public void Close() => Console.WriteLine("PostgreSQL connection closed.");
}

// 工厂
public static class DbConnectionFactory
{
    public static IMyDbConnection Create(string dbType, string connectionString)
    {
        return dbType.ToLower() switch
        {
            "sqlserver" => new SqlServerConnection(connectionString),
            "mysql" => new MySqlConnection(connectionString),
            "postgresql" => new PostgreSqlConnection(connectionString),
            _ => throw new ArgumentException($"Unsupported database type: {dbType}")
        };
    }
}

// 客户端调用
public class Program
{
    public static void Main()
    {
        var conn = DbConnectionFactory.Create("mysql", "Server=localhost;Database=test");
        conn.Open();
        // 执行数据库操作...
        conn.Close();
    }
}

场景3: 支付处理工厂(Payment Processing Factory)

根据不同支付方式创建对应的支付处理器,实现支付系统的可扩展性。

csharp 复制代码
using System;

// 抽象产品
public interface IPaymentProcessor
{
    bool ProcessPayment(decimal amount);
    string GetPaymentMethod();
}

// 具体产品 - 信用卡支付
public class CreditCardPayment : IPaymentProcessor
{
    private string _cardNumber;
    public CreditCardPayment(string cardNumber) { _cardNumber = cardNumber; }

    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing credit card payment of ¥{amount:F2} with card {_cardNumber[^4..]}");
        return true;
    }

    public string GetPaymentMethod() => "Credit Card";
}

// 具体产品 - 微信支付
public class WeChatPayment : IPaymentProcessor
{
    private string _openId;
    public WeChatPayment(string openId) { _openId = openId; }

    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing WeChat payment of ¥{amount:F2} for user {_openId}");
        return true;
    }

    public string GetPaymentMethod() => "WeChat Pay";
}

// 具体产品 - 支付宝
public class AlipayPayment : IPaymentProcessor
{
    private string _accountId;
    public AlipayPayment(string accountId) { _accountId = accountId; }

    public bool ProcessPayment(decimal amount)
    {
        Console.WriteLine($"Processing Alipay payment of ¥{amount:F2} for account {_accountId}");
        return true;
    }

    public string GetPaymentMethod() => "Alipay";
}

// 工厂
public static class PaymentProcessorFactory
{
    public static IPaymentProcessor Create(string paymentMethod, string accountInfo)
    {
        return paymentMethod.ToLower() switch
        {
            "creditcard" => new CreditCardPayment(accountInfo),
            "wechat" => new WeChatPayment(accountInfo),
            "alipay" => new AlipayPayment(accountInfo),
            _ => throw new ArgumentException($"Unsupported payment method: {paymentMethod}")
        };
    }
}

// 客户端调用
public class Program
{
    public static void Main()
    {
        var payment = PaymentProcessorFactory.Create("wechat", "user_12345");
        payment.ProcessPayment(99.99m);
        Console.WriteLine($"Paid via {payment.GetPaymentMethod()}");
    }
}

✅ 优点

  • 解耦:客户端不需要知道具体产品类名,只需知道参数即可
  • 扩展性:新增产品时,工厂方法模式只需增加新的工厂子类
  • 复用性:工厂方法可以被多次调用,避免重复的创建逻辑
  • 符合单一职责原则:将对象的创建逻辑集中管理

❌ 缺点

  • 类数量增加:每增加一个产品就需要增加一个具体工厂类
  • 简单工厂违反开闭原则:修改工厂逻辑需要修改原有代码
  • 增加了系统的抽象性和理解难度

📊 与其他模式对比

模式 区别
抽象工厂 创建一系列相关对象族,工厂模式创建单一产品
建造者模式 关注分步构建复杂对象,工厂关注一步创建
原型模式 通过克隆创建对象,工厂通过new创建对象
单例模式 保证唯一实例,工厂可以创建多个不同实例
相关推荐
淡海水1 小时前
05-02-源码-Boehm GC标记阶段
算法·unity·c#·游戏引擎·gc
信可维1 小时前
AI 读 Word 表格总读错?先查合并单元格和表头这 3 处
开发语言·人工智能·c#·word·软件工程
日和雫2 小时前
封装、继承、多态 & 组合,为什么组合大于继承?
设计模式
半摆烂日常3 小时前
手机表单的左滑操作:触摸事件的处理细节
大数据·开发语言·人工智能·智能手机·https·c#
绛橘色的日落(。・∀・)ノ4 小时前
C#学习笔记
笔记·学习·c#
asdzx674 小时前
C# 将 HTML 转换为 PDF:基于 Chrome 的转换方案
pdf·c#·html
1-1=05 小时前
.NET 实现后台任务
c#·.net·.netcore·quartz·hangfire
步步为营DotNet5 小时前
从分代预算到 DATAS:.NET GC 调优到底在调什么
c#·.net·内存管理·gc·datas
淡海水5 小时前
05-03-源码-Boehm GC分配与碎片管理
开发语言·算法·unity·c#·游戏引擎·gc
代钦塔拉5 小时前
【C++/Qt 进阶】设计模式系列(6):桥接模式——把“两个独立变化的维度“拆开
c++·qt·设计模式