简单工厂模式 (Simple Factory)
简单工厂模式虽然不属于GoF 23种设计模式,但它是最常用、最基础的设计模式之一,特别适合初学者理解工厂概念。
简单工厂模式详解
目的:定义一个工厂类,根据传入的参数不同返回不同的实例,被创建的实例通常具有共同的父类。
优点:
- 客户端与具体产品类解耦
- 将对象的创建集中管理,便于维护
- 不需要记住具体类名,只需要知道参数
缺点:
- 工厂类职责过重,增加新产品需要修改工厂类
- 不符合开闭原则
csharp
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(); // 创建产品A
case "B":
Console.WriteLine("Factory: Creating Product B");
return new ConcreteProductB(); // 创建产品B
case "C":
Console.WriteLine("Factory: Creating Product C");
return new ConcreteProductC(); // 创建产品C
default:
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(); // 创建产品A
case ProductType.B:
Console.WriteLine("Factory: Creating Product B");
return new ConcreteProductB(); // 创建产品B
case ProductType.C:
Console.WriteLine("Factory: Creating Product C");
return new ConcreteProductC(); // 创建产品C
default:
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
*/
实际应用场景示例:数据库连接工厂
csharp
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 Server
return new SqlServerConnection();
}
else if (connectionString.ToLower().Contains("server=mysql"))
{
Console.WriteLine("Detected MySQL from connection string"); // 从连接字符串检测到MySQL
return new MySqlConnection();
}
else if (connectionString.ToLower().Contains("server=oracle"))
{
Console.WriteLine("Detected Oracle from connection string"); // 从连接字符串检测到Oracle
return 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 Database
2. 创建MySQL连接:
Creating MySQL connection...
Connected to MySQL Database
MySQL executed: SELECT * FROM Products
Disconnected from MySQL Database
3. 通过连接字符串创建Oracle连接:
Detected Oracle from connection string
Connected to Oracle Database
Oracle executed: SELECT * FROM Orders
Disconnected from Oracle Database
=== 工厂模式优势总结 ===
✓ 客户端与具体数据库类解耦
✓ 新增数据库类型只需修改工厂类
✓ 统一的创建接口,便于管理
*/
静态简单工厂
csharp
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(); // 创建产品A
case "B":
Console.WriteLine("Static Factory: Creating Product B");
return new ConcreteProductB(); // 创建产品B
case "C":
Console.WriteLine("Static Factory: Creating Product C");
return new ConcreteProductC(); // 创建产品C
default:
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 抽象工厂
模式 | 特点 | 适用场景 |
---|---|---|
简单工厂 | 一个工厂类,根据参数创建不同产品 | 产品类型不多,创建逻辑简单 |
工厂方法 | 每个产品对应一个工厂类 | 产品类型多,需要扩展性好 |
抽象工厂 | 创建产品家族,确保兼容性 | 需要创建相关产品组 |
总结
简单工厂模式是最容易理解和使用的创建型模式,它的核心思想是:
- 封装变化:将对象的创建过程封装起来
- 解耦:客户端不需要知道具体产品的类名
- 集中管理:所有创建逻辑在一个地方维护
使用时机:
- 当需要创建的对象类型不多时
- 客户端不关心对象的创建细节时
- 需要统一管理对象创建时
注意事项:
- 当产品类型很多时,工厂类会变得臃肿
- 新增产品需要修改工厂类,违反开闭原则
- 考虑使用工厂方法模式来避免这些问题
简单工厂是理解更复杂工厂模式的基础,在实际项目中非常实用!