工厂来创建数据库交互
本文关键字:交互 数据库 创建 工厂 | 更新日期: 2023-09-27 18:29:23
我已经编写了一个用于访问数据库的DLL。因此,我有一个名为IDbInterop的接口,它看起来像:
public interface IDbInterop
{
void ExecuteCommandNonQuery(string commandText, params IDbParameter[] commandParameter);
object ExecuteCommandScalar(string commandText, params IDbParameter[] commandParameter);
DataSet ExecuteCommandDataSet(string commandText, params IDbParameter[] commandParameter);
}
为了为特定的数据库提供程序获取该接口的实例,我引入了一个工厂,它以枚举为参数来决定应该创建哪个具体实现:
public static class DbInteropFactory
{
public static IDbInterop BuildDbInterop(DbType dbType, string connectionString)
{
switch (dbType)
{
case DbType.MSSQL:
return new MSSQLDbInterop(connectionString);
default:
throw new ArgumentOutOfRangeException("dbType");
}
}
}
public enum DbType
{
MSSQL,
}
到目前为止,我只实现了MSSQL数据库的具体实现。现在,如果应该添加另一个数据库提供程序,我必须执行以下步骤:
- 为具体实现创建一个类(例如MySqlDbInterop)
- 扩展枚举(例如MYSQL)
- 扩展工厂以允许用户获得新的实现
有没有一种方法,如果添加了新的实现,我就不必扩展枚举和工厂?
是的,我知道至少有三种方法。
- 您可以使用
Reflection
来实例化具体的类,但可能需要处理任何性能问题 - 您可以让具体类向工厂注册,但需要确保在任何客户端请求其实例之前进行注册
- 您可以使用任何可用的IoC容器,这些容器使用依赖注入(Constructor或Setter Injection)原理为您实例化具体类。这些IoC容器内部可以再次使用如第一点中所述的CCD_ 2
是的,有一种方法。使用工厂工人。工作人员创建一个实例,并具有匹配参数的知识。
public interface IFactoryWorker
{
IDbInterop CreateInterop( string connectionString );
bool AcceptParameters( string ProviderName );
}
就是一个例子
public class SqlServerFactoryWorker : IFactoryWorker
{
public IDbInterop CreateInterop( string connectionString )
{
return new MSSQLDbInterop(connectionString);
}
public bool AcceptParameters( string providerName )
{
return providerName == "System.Data.SqlClient";
}
}
然后你的工厂变成
public static class DbInteropFactory
{
private static List<IFactoryWorker> _workers;
static DbInteropFactory()
{
_workers = new List<IFactoryWorker>();
_workers.Add( new SqlServerFactoryWorker() );
}
public static void AddWorker( IFactoryWorker worker )
{
_workers.Add( worker );
}
public static IDbInterop BuildDbInterop(
string ProviderName, string connectionString)
{
foreach ( var worker in _workers )
{
if ( worker.AcceptParameters( ProviderName ) )
return worker.CreateInterop( connectionString );
// or return null
throw new ArgumentException();
}
}
这种方法有以下好处:
- 将字符串作为提供程序类型意味着您不必扩展任何枚举
- 让工人离开工厂意味着你永远不必改变工厂本身
- 创建新的提供程序意味着创建一个新的辅助程序并在工厂中注册,这可以在工厂外使用
AddWorker
方法完成
这种方法遵循开闭原则。
为了简化代码,您可以使工作程序成为实际的互操作提供程序。这意味着工作接口应该继承IDbInterop
并实现所有逻辑。在这种方法中,工厂试图定位"工作提供者"(foreach ( var worker in _workers
),并在找到时返回:
public interface IFactoryWorker : IDbInterop
{
IDbInterop CreateInterop( string connectionString );
bool AcceptParameters( string ProviderName );
}
...
foreach ( var worker in _workers )
{
if ( worker.AcceptParameters( ProviderName ) )
return worker;
// or return null
throw new ArgumentException();
}
这伴随着违反单一责任原则的代价。