C# 中的 简单工厂模式 (Simple Factory)
简单工厂模式 (Simple Factory)
简单工厂模式虽然不属于GoF 23种设计模式,但它是最常用、最基础的设计模式之一,特别适合初学者理解工厂概念。
简单工厂模式详解
目的:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例通常具有共同的父类。
优点:
- 客户端与具体产品类解耦
- 将对象的创建集中管理,便于维护
- 不需要记住具体类名,只需要知道参数
缺点:
- 工厂类职责过重,增加新产品需要修改工厂类
- 不符合开闭原则
using System;// 产品接口
public interface IProduct
{string Operation(); // 产品操作
}// 具体产品A
public class ConcreteProductA : IProduct
{public string Operation(){return "Result of ConcreteProductA"; // 产品A的具体操作}
}// 具体产品B
public class ConcreteProductB : IProduct
{public string Operation(){return "Result of ConcreteProductB"; // 产品B的具体操作}
}// 具体产品C
public class ConcreteProductC : IProduct
{public string Operation(){return "Result of ConcreteProductC"; // 产品C的具体操作}
}// 简单工厂类
public class SimpleFactory
{// 根据类型参数创建不同的产品public IProduct CreateProduct(string type){switch (type.ToUpper()){case "A":Console.WriteLine("Factory: Creating Product A");return new ConcreteProductA(); // 创建产品Acase "B":Console.WriteLine("Factory: Creating Product B");return new ConcreteProductB(); // 创建产品Bcase "C":Console.WriteLine("Factory: Creating Product C");return new ConcreteProductC(); // 创建产品Cdefault:throw new ArgumentException($"Invalid product type: {type}"); // 无效类型异常}}// 使用枚举的版本,更安全public IProduct CreateProduct(ProductType type){switch (type){case ProductType.A:Console.WriteLine("Factory: Creating Product A");return new ConcreteProductA(); // 创建产品Acase ProductType.B:Console.WriteLine("Factory: Creating Product B");return new ConcreteProductB(); // 创建产品Bcase ProductType.C:Console.WriteLine("Factory: Creating Product C");return new ConcreteProductC(); // 创建产品Cdefault:throw new ArgumentException($"Invalid product type: {type}"); // 无效类型异常}}
}// 产品类型枚举
public enum ProductType
{A,B,C
}// 客户端代码
class Program
{static void Main(){// 创建工厂实例var factory = new SimpleFactory();Console.WriteLine("=== 使用字符串参数版本 ===");// 客户端不需要知道具体产品类,只需要知道类型标识IProduct productA = factory.CreateProduct("A");Console.WriteLine($"Client: {productA.Operation()}"); // 输出产品A的操作结果IProduct productB = factory.CreateProduct("B");Console.WriteLine($"Client: {productB.Operation()}"); // 输出产品B的操作结果IProduct productC = factory.CreateProduct("C");Console.WriteLine($"Client: {productC.Operation()}"); // 输出产品C的操作结果Console.WriteLine("\n=== 使用枚举参数版本(推荐) ===");// 使用枚举更安全,避免拼写错误IProduct productA2 = factory.CreateProduct(ProductType.A);Console.WriteLine($"Client: {productA2.Operation()}"); // 输出产品A的操作结果IProduct productB2 = factory.CreateProduct(ProductType.B);Console.WriteLine($"Client: {productB2.Operation()}"); // 输出产品B的操作结果Console.WriteLine("\n=== 演示异常处理 ===");try{// 尝试创建不存在的产品类型IProduct invalidProduct = factory.CreateProduct("X");}catch (ArgumentException ex){Console.WriteLine($"Error: {ex.Message}"); // 输出错误信息}}
}/* 输出结果:
=== 使用字符串参数版本 ===
Factory: Creating Product A
Client: Result of ConcreteProductA
Factory: Creating Product B
Client: Result of ConcreteProductB
Factory: Creating Product C
Client: Result of ConcreteProductC=== 使用枚举参数版本(推荐) ===
Factory: Creating Product A
Client: Result of ConcreteProductA
Factory: Creating Product B
Client: Result of ConcreteProductB=== 演示异常处理 ===
Error: Invalid product type: X
*/
实际应用场景示例:数据库连接工厂
using System;// 数据库连接接口
public interface IDatabaseConnection
{void Connect(); // 连接数据库void Disconnect(); // 断开连接string Query(string sql); // 执行查询
}// SQL Server 连接
public class SqlServerConnection : IDatabaseConnection
{public void Connect(){Console.WriteLine("Connected to SQL Server Database"); // 连接SQL Server}public void Disconnect(){Console.WriteLine("Disconnected from SQL Server Database"); // 断开SQL Server连接}public string Query(string sql){return $"SQL Server executed: {sql}"; // SQL Server执行查询}
}// MySQL 连接
public class MySqlConnection : IDatabaseConnection
{public void Connect(){Console.WriteLine("Connected to MySQL Database"); // 连接MySQL}public void Disconnect(){Console.WriteLine("Disconnected from MySQL Database"); // 断开MySQL连接}public string Query(string sql){return $"MySQL executed: {sql}"; // MySQL执行查询}
}// Oracle 连接
public class OracleConnection : IDatabaseConnection
{public void Connect(){Console.WriteLine("Connected to Oracle Database"); // 连接Oracle}public void Disconnect(){Console.WriteLine("Disconnected from Oracle Database"); // 断开Oracle连接}public string Query(string sql){return $"Oracle executed: {sql}"; // Oracle执行查询}
}// 数据库类型枚举
public enum DatabaseType
{SqlServer,MySql,Oracle
}// 数据库连接工厂
public class DatabaseConnectionFactory
{// 创建数据库连接public IDatabaseConnection CreateConnection(DatabaseType dbType){switch (dbType){case DatabaseType.SqlServer:Console.WriteLine("Creating SQL Server connection..."); // 创建SQL Server连接return new SqlServerConnection();case DatabaseType.MySql:Console.WriteLine("Creating MySQL connection..."); // 创建MySQL连接return new MySqlConnection();case DatabaseType.Oracle:Console.WriteLine("Creating Oracle connection..."); // 创建Oracle连接return new OracleConnection();default:throw new ArgumentException($"Unsupported database type: {dbType}"); // 不支持的数据库类型}}// 从配置字符串创建连接(更灵活的方式)public IDatabaseConnection CreateConnection(string connectionString){if (connectionString.ToLower().Contains("server=sql")){Console.WriteLine("Detected SQL Server from connection string"); // 从连接字符串检测到SQL Serverreturn new SqlServerConnection();}else if (connectionString.ToLower().Contains("server=mysql")){Console.WriteLine("Detected MySQL from connection string"); // 从连接字符串检测到MySQLreturn new MySqlConnection();}else if (connectionString.ToLower().Contains("server=oracle")){Console.WriteLine("Detected Oracle from connection string"); // 从连接字符串检测到Oraclereturn new OracleConnection();}else{throw new ArgumentException("Unable to determine database type from connection string"); // 无法从连接字符串确定数据库类型}}
}// 客户端代码
class Program
{static void Main(){// 创建数据库连接工厂var dbFactory = new DatabaseConnectionFactory();Console.WriteLine("=== 数据库连接工厂演示 ===\n");// 创建SQL Server连接Console.WriteLine("1. 创建SQL Server连接:");IDatabaseConnection sqlConn = dbFactory.CreateConnection(DatabaseType.SqlServer);sqlConn.Connect(); // 连接数据库Console.WriteLine(sqlConn.Query("SELECT * FROM Users")); // 执行查询sqlConn.Disconnect(); // 断开连接Console.WriteLine();// 创建MySQL连接Console.WriteLine("2. 创建MySQL连接:");IDatabaseConnection mysqlConn = dbFactory.CreateConnection(DatabaseType.MySql);mysqlConn.Connect(); // 连接数据库Console.WriteLine(mysqlConn.Query("SELECT * FROM Products")); // 执行查询mysqlConn.Disconnect(); // 断开连接Console.WriteLine();// 通过连接字符串创建连接Console.WriteLine("3. 通过连接字符串创建Oracle连接:");IDatabaseConnection oracleConn = dbFactory.CreateConnection("Server=oracle;Database=test;Uid=user;Pwd=pass;");oracleConn.Connect(); // 连接数据库Console.WriteLine(oracleConn.Query("SELECT * FROM Orders")); // 执行查询oracleConn.Disconnect(); // 断开连接Console.WriteLine("\n=== 工厂模式优势总结 ===");Console.WriteLine("✓ 客户端与具体数据库类解耦");Console.WriteLine("✓ 新增数据库类型只需修改工厂类");Console.WriteLine("✓ 统一的创建接口,便于管理");}
}/* 输出结果:
=== 数据库连接工厂演示 ===1. 创建SQL Server连接:
Creating SQL Server connection...
Connected to SQL Server Database
SQL Server executed: SELECT * FROM Users
Disconnected from SQL Server Database2. 创建MySQL连接:
Creating MySQL connection...
Connected to MySQL Database
MySQL executed: SELECT * FROM Products
Disconnected from MySQL Database3. 通过连接字符串创建Oracle连接:
Detected Oracle from connection string
Connected to Oracle Database
Oracle executed: SELECT * FROM Orders
Disconnected from Oracle Database=== 工厂模式优势总结 ===
✓ 客户端与具体数据库类解耦
✓ 新增数据库类型只需修改工厂类
✓ 统一的创建接口,便于管理
*/
静态简单工厂
using System;// 静态简单工厂 - 不需要实例化工厂类
public static class StaticSimpleFactory
{// 静态方法创建产品public static IProduct CreateProduct(string type){switch (type.ToUpper()){case "A":Console.WriteLine("Static Factory: Creating Product A");return new ConcreteProductA(); // 创建产品Acase "B":Console.WriteLine("Static Factory: Creating Product B");return new ConcreteProductB(); // 创建产品Bcase "C":Console.WriteLine("Static Factory: Creating Product C");return new ConcreteProductC(); // 创建产品Cdefault:throw new ArgumentException($"Invalid product type: {type}"); // 无效类型异常}}// 泛型版本,更灵活public static T CreateProduct<T>() where T : IProduct, new(){Console.WriteLine($"Static Factory: Creating {typeof(T).Name}");return new T(); // 创建泛型指定的产品}
}// 使用静态工厂的客户端代码
class StaticFactoryClient
{static void Main(){Console.WriteLine("=== 静态简单工厂演示 ===\n");// 使用字符串参数IProduct productA = StaticSimpleFactory.CreateProduct("A");Console.WriteLine($"Client: {productA.Operation()}"); // 输出产品A的操作结果// 使用泛型版本IProduct productB = StaticSimpleFactory.CreateProduct<ConcreteProductB>();Console.WriteLine($"Client: {productB.Operation()}"); // 输出产品B的操作结果Console.WriteLine("\n=== 静态工厂优势 ===");Console.WriteLine("✓ 无需创建工厂实例");Console.WriteLine("✓ 调用更简洁");Console.WriteLine("✓ 适合简单的创建逻辑");}
}/* 输出结果:
=== 静态简单工厂演示 ===Static Factory: Creating Product A
Client: Result of ConcreteProductA
Static Factory: Creating ConcreteProductB
Client: Result of ConcreteProductB=== 静态工厂优势 ===
✓ 无需创建工厂实例
✓ 调用更简洁
✓ 适合简单的创建逻辑
*/
简单工厂 vs 工厂方法 vs 抽象工厂
模式 | 特点 | 适用场景 |
---|---|---|
简单工厂 | 一个工厂类,根据参数创建不同产品 | 产品类型不多,创建逻辑简单 |
工厂方法 | 每个产品对应一个工厂类 | 产品类型多,需要扩展性好 |
抽象工厂 | 创建产品家族,确保兼容性 | 需要创建相关产品组 |
总结
简单工厂模式是最容易理解和使用的创建型模式,它的核心思想是:
- 封装变化:将对象的创建过程封装起来
- 解耦:客户端不需要知道具体产品的类名
- 集中管理:所有创建逻辑在一个地方维护
使用时机:
- 当需要创建的对象类型不多时
- 客户端不关心对象的创建细节时
- 需要统一管理对象创建时
注意事项:
- 当产品类型很多时,工厂类会变得臃肿
- 新增产品需要修改工厂类,违反开闭原则
- 考虑使用工厂方法模式来避免这些问题
简单工厂是理解更复杂工厂模式的基础,在实际项目中非常实用!