我已经编写了一个用于访问数据库的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数据库实现了一个concret实现。现在,如果要添加另一个数据库提供者,我将不得不执行以下步骤:
有没有办法,如果添加新的实现,我不必扩展枚举和工厂?
答案 0 :(得分:1)
是的,至少有三种我知道的方式。
Reflection
来实例化具体类,但您可能必须处理任何性能问题。Reflection
,如第一点所述。答案 1 :(得分:0)
是的,有办法。使用工厂工人。工作人员创建实例并具有匹配参数的知识。
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
方法在工厂外完成这种方法遵循开放 - 封闭原则。
为了简化代码,您可以使工作人员成为实际的互操作提供者。这意味着worker接口应该继承自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();
}
这是违反单一责任原则的成本。