工厂来创建数据库交互

本文关键字:交互 数据库 创建 工厂 | 更新日期: 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)
  • 扩展工厂以允许用户获得新的实现

有没有一种方法,如果添加了新的实现,我就不必扩展枚举和工厂?

工厂来创建数据库交互

是的,我知道至少有三种方法。

  1. 您可以使用Reflection来实例化具体的类,但可能需要处理任何性能问题
  2. 您可以让具体类向工厂注册,但需要确保在任何客户端请求其实例之前进行注册
  3. 您可以使用任何可用的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();
     }

这伴随着违反单一责任原则的代价。