C# 中的抽象工厂设计模式
在本文中,您将学习抽象工厂设计模式、其组件以及 C# 中的一个真实示例,以了解如何在实际场景中使用它。
抽象工厂定义
抽象工厂设计模式是一种创建型模式,它提供一个接口来创建相关或依赖对象的家族,而无需指定它们的具体类。它允许客户端代码创建属于同一家族的不同类型的对象。
这里,相关或依赖对象是指旨在一起使用以实现共同目标的一组对象。它强调某些对象应作为一个内聚组一起创建。抽象工厂提供一个抽象类或接口来创建这些对象,而具体工厂实现此抽象类或接口以生成特定家族的相关或依赖对象。
抽象工厂组件
以下是抽象工厂设计模式的组件
- 抽象工厂:这可以是声明用于创建相关抽象产品对象的方法的抽象类或接口。
- 具体工厂:这些是实现抽象工厂接口或抽象类并提供用于创建抽象产品对象的实现的类。
- 抽象产品:这些是定义抽象工厂可以创建的相关或依赖产品的共同行为的抽象类或接口。
- 具体产品:这些是实现抽象产品接口或抽象类并提供抽象产品实现的类。具体工厂将创建并返回这些类的对象。
- 客户端:这是一个使用抽象工厂创建产品对象的类。它不使用“new”关键字创建具体产品的对象,而是使用抽象工厂对象来获取具体产品的对象。
下图显示了抽象工厂组件及其之间的关系。

让我们开始创建抽象产品接口和具体产品类。请记住,具体产品应该是相关或依赖类,以实现共同功能。
// Abstract Product A
interface IAbstractProductA
{
void ExecuteProductA();
}
// Concrete Product A 1
class ConcreteProductA1 : IAbstractProductA
{
public void ExecuteProductA()
{
Console.WriteLine("Executing ConcreteProductA1");
}
}
// Concrete Product A 2
class ConcreteProductA2 : IAbstractProductA
{
public void ExecuteProductA()
{
Console.WriteLine("Executing ConcreteProductA2");
}
}
// Abstract Product B
interface IAbstractProductB
{
void ExecuteProductB(IAbstractProductA prodA);
}
// Concrete Product B 1
class ConcreteProductB1 : IAbstractProductB
{
public void ExecuteProductB(IAbstractProductA prodA)
{
Console.WriteLine("Inside ConcreteProductB1");
prodA.ExecuteProductA();
}
}
// Concrete Product B 2
class ConcreteProductB2 : IAbstractProductB
{
public void ExecuteProductB(IAbstractProductA prodA)
{
Console.WriteLine("Inside ConcreteProductB2");
prodA.ExecuteProductA();
}
}
在上面的代码中,抽象产品 IAbstractProductA
和 IAbstractProductB
是定义具体产品必须实现的方法的接口。请注意,IAbstractProductB
包含一个与 IAbstractProductA
通信的方法,仅用于展示它们是依赖或相关产品。
具体产品 ConcreteProductA1
、ConcreteProductA2
、ConcreteProductB1
和 ConcreteProductB2
分别实现相应的抽象产品接口。它们提供接口中定义的操作的具体实现。
因此,这些是我们的相关产品实现,用于实现某些功能。现在,让我们创建一个抽象工厂和具体工厂,它们创建并返回上述具体产品的对象,如下所示。
// Abstract Factory
interface IAbstractFactory
{
IAbstractProductA CreateProductA();
IAbstractProductB CreateProductB();
}
// Concrete Factory 1
class ConcreteFactory1 : IAbstractFactory
{
public IAbstractProductA CreateProductA()
{
return new ConcreteProductA1();
}
public IAbstractProductB CreateProductB()
{
return new ConcreteProductB1();
}
}
// Concrete Factory 2
class ConcreteFactory2 : IAbstractFactory
{
public IAbstractProductA CreateProductA()
{
return new ConcreteProductA2();
}
public IAbstractProductB CreateProductB()
{
return new ConcreteProductB2();
}
}
在上面的代码中,IAbstractFactory
接口表示一个抽象工厂,它定义了 CreateProductA()
和 CreateProductB()
方法,分别用于创建 IAbstractProductA
和 IAbstractProductB
的实例。请注意,您可以根据您的要求使用抽象类而不是接口。
具体工厂 ConcreteFactory1
和 ConcreteFactory2
实现 IAbstractFactory
接口并重写方法以创建两个具体产品。
现在,让我们看看客户端类如何使用这个抽象工厂来获取具体产品的对象。
// Client
class Client
{
private IAbstractProductA _productA;
private IAbstractProductB _productB;
public Client(IAbstractFactory factory)
{
_productA = factory.CreateProductA();
_productB = factory.CreateProductB();
}
public void Execute()
{
_productA.ExecuteProductA();
_productB.ExecuteProductB(_productA);
}
}
Client
类在其构造函数中接收抽象工厂的实例。然后它使用工厂创建抽象产品(IAbstractProductA
和 IAbstractProductB
)的实例。客户端可以在创建的产品上执行操作。
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Using factory1");
IAbstractFactory factory1 = new ConcreteFactory1();
Client client1 = new Client(factory1);
client1.Execute();
Console.WriteLine("Using factory2");
IAbstractFactory factory2 = new ConcreteFactory2();
Client client2 = new Client(factory2);
client2.Execute();
}
}
Main
方法通过创建不同工厂(ConcreteFactory1
和 ConcreteFactory2
)的实例并将它们传递给 Client
构造函数来演示抽象工厂模式的使用。然后客户端使用这些工厂来创建和执行产品。
现在,让我们根据抽象工厂模式创建一个新的 DBConnectionFactory
示例。
真实世界的例子
让我们考虑一个真实的例子,您的应用程序中访问多个数据库。假设您需要连接到 SQL Server 和 PostgreSQL 数据库以在您的应用程序中保存或检索一些数据。在这种情况下,我们可以使用抽象工厂设计模式来创建数据库工厂和其他组件。
using System;
//Abstract Product
interface IDBConnection
{
void Connect();
}
//Concrete Product
class SQLServerDBConnection : IDBConnection
{
public void Connect()
{
Console.WriteLine("Connected to SQL Server database...");
}
}
//Concrete Product
class PostgreDBConnection : IDBConnection
{
public void Connect()
{
Console.WriteLine("Connected to PostGre database.");
}
}
//Abstract Product
interface IDBCommand
{
void Execute(string query, IDBConnection con);
}
//Concrete Product
class SQLServerDBCommand : IDBCommand
{
public void Execute(string query, IDBConnection con)
{
con.Connect();
Console.WriteLine("Executing SQL Server query: " + query);
}
}
//Concrete Product
class PostgreDBCommand : IDBCommand
{
public void Execute(string query, IDBConnection con)
{
con.Connect();
Console.WriteLine("Executing PostGreSQL Server query: " + query);
}
}
//Abstract Factory
interface IDBFactory
{
IDBConnection CreateConnection();
IDBCommand CreateCommand();
}
//Concrete Factory for SQL Server
class SQLServerFactory : IDBFactory
{
public IDBConnection CreateConnection()
{
return new SQLServerDBConnection();
}
public IDBCommand CreateCommand()
{
return new SQLServerDBCommand();
}
}
// Concrete Factory for PostgreSQL
class PostGreSQLFactory : IDBFactory
{
public IDBConnection CreateConnection()
{
return new PostgreDBConnection();
}
public IDBCommand CreateCommand()
{
return new PostgreDBCommand();
}
}
//Client
class DBQueryClient
{
private IDBConnection _connection;
private IDBCommand _command;
public DBQueryClient(IDBFactory factory)
{
_connection = factory.CreateConnection();
_command = factory.CreateCommand();
}
public void ExecuteQuery(string query)
{
_command.Execute(query, _connection);
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Using SQL Server Factory");
IDBFactory sqlServerFactory = new SQLServerFactory();
DBQueryClient sqlServerClient = new DBQueryClient(sqlServerFactory);
sqlServerClient.ExecuteQuery("SELECT * FROM Customers");
Console.WriteLine("
Using PostGre Factory");
IDBFactory postgreFactory = new PostGreSQLFactory();
DBQueryClient postgreClient = new DBQueryClient(postgreFactory);
postgreClient.ExecuteQuery("SELECT * FROM Customers");
}
}
Using SQL Server Factory Connected to SQL Server database... Executing SQL Server query: SELECT * FROM Customers Using PostGre Factory Connected to PostGre database. Executing PostGreSQL Server query: SELECT * FROM Customers
在上面的示例中,我们定义了两个抽象产品接口:IDBConnection
和 IDBCommand
。IDBConnection
定义了连接数据库的方法,IDBCommand
定义了执行数据库查询的方法。这些是依赖的抽象产品,因为 IDBCommand
需要一个 IDBConnection
对象来执行查询。
接下来,SQLServerDBConnection
和 PostgreDBConnection
是实现 IDBConnection
接口的具体产品类。这两个类都实现了 Connect
方法以建立与相应数据库的连接。
同样,SQLServerDBCommand
和 PostgreDBCommand
是实现 IDBCommand
接口的具体产品类。这些类实现了 Execute
方法以在各自的数据库上执行查询。
一个名为 IDBFactory
的抽象工厂接口。此接口定义了负责创建 IDBConnection
和 IDBCommand
实例的工厂方法。
SQLServerFactory
和 PostGreSQLFactory
是实现 CreateConnection
和 CreateCommand
方法以创建相应具体产品类实例的具体工厂。
现在,DBQueryClient
是客户端类,它根据传入的工厂类查询数据库。此类在其构造函数中接受抽象工厂的实例,并使用它创建具体产品实例。然后,DBQueryClient
利用创建的 IDBConnection
和 IDBCommand
对象在数据库上执行查询。
最后,在 Main
方法中,代码演示了抽象工厂和创建对象的使用。它使用 SQLServerFactory
创建客户端,使用创建的对象执行查询,然后使用 PostGreSQLFactory
重复该过程。
通过此实现,抽象工厂模式提供了一个接口,用于创建相关对象家族,而无需指定它们的具体类,从而允许客户端可互换地使用任何可用家族。
因此,抽象工厂设计模式提供了一种在不指定具体类的情况下创建相关或依赖对象家族的方法。它促进了松散耦合,并允许在创建对象时轻松扩展和灵活。通过使用抽象工厂模式,您可以轻松地在应用程序中切换不同的对象家族,而不会影响客户端代码。