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创建对象
单例模式 保证唯一实例,工厂可以创建多个不同实例
相关推荐
我是唐青枫2 小时前
C#.NET YARP 服务发现实战:接入 Consul 和 Kubernetes 动态发现后端服务
c#·服务发现·.net
魔法阵维护师2 小时前
从零开发游戏需要学习的c#模块,第三十章(掉落物品 —— 血包与能量)
学习·游戏·c#
阿狸猿3 小时前
论软件设计模式及其应用
设计模式
workflower3 小时前
具身智能-三层结构
人工智能·设计模式·动态规划·软件工程·scrum
我爱cope3 小时前
【Agent智能体10 | 反思设计模式-AI数据分析的可视化实战】
人工智能·设计模式·数据分析
z落落3 小时前
C# ArrayList 动态集合(接口/区别/API/深浅拷贝)+ List<T> 泛型集合
开发语言·c#
老码观察3 小时前
设计模式实战解读(七):适配器模式——让不兼容的接口无缝协作
java·设计模式·适配器模式
游乐码4 小时前
unity基础(八)协程
游戏·unity·c#·游戏引擎
Xin_ye100864 小时前
C# 零基础到精通教程 - 第十六章:ASP.NET Core Web API——构建现代 Web 服务
开发语言·c#