我怎样才能更好地设计这个? (避免使用面向对象设计的switch语句)

我对面向对象的设计有点了解,但我不确定如何在我的代码中使用这些原则。 这是我正在做的事情:

public void Query(Agency agency, Citation queryCitation) { queryCitation.AgencyCode = agency.AgencyCode; switch (agency.ClientDb.Type) { case "SQL": QueryOracle(agency, queryCitation); break; case "PIC": QueryPick(agency, queryCitation); break; } } 

(其中大部分是来自NHibernate的对象。我正在使用遗留数据库系统并将其部分重构到代码库中。)显然,我可以在这里做一些不同的事情,这样我就不需要为不同的数据库提供重复的function了。具有相同输入的查询。 它应该根据代理对象知道是使用Oracle数据库还是选择数据库连接。 (如果你从未听说过Pick数据库,那么直到我开始在这里工作之前我都没有。我们通过HTTP请求对它进行查询,所以它不是SQL。)

我应该创建一个接口,例如名为“ClientDbConnection”,然后创建两个实现该接口的类,移动代码查询数据库,然后使用“agency.clientDb.Query(queryCitation)”替换整个函数? 我想我在这里大声思考,但对此的任何意见都将不胜感激。

机构是你控制的一个class级吗? 如果这样做的话:

 public abstract class GenericDb { public abstract void Query(parms); } 

在您的代理机构类中,您可以拥有

 public GenericDb ClientDb {get; set;} 

然后有一个SqlDb类,如:

 public class SqlDb : GenericDb { public void Query(parms); } public class PicDb : GenericDb { public void Query(parms); } 

那么这段代码:

 public void Query(Agency agency, Citation queryCitation) { queryCitation.AgencyCode = agency.AgencyCode; switch (agency.ClientDb.Type) { case "SQL": QueryOracle(agency, queryCitation); break; case "PIC": QueryPick(agency, queryCitation); break; } } 

 public void Query(Agency agency, Citation queryCitation) { queryCitation.AgencyCode = agency.AgencyCode; agency.ClientDb.Query(queryCitation); } 

由于inheritance,它将知道ClientDb具有GenericDb的基类。 它将通过ClientDb参数的类型知道它是应该运行SqlDb还是PicDb或Oracle等。

您可能希望在此处实施策略模式。 基本上,switch语句中的每个可能的“类型”都将成为它自己的一个实现相同接口的类。

应用战略模式

然后,您可以使用以“type”值作为参数的工厂方法。 该方法将返回正确的类(其返回类型是上面提到的接口)。

我会重构利用接口。 我可能会这样做:

 public interface IQuery { void Execute(Agency agency, Citation query); } public class OracleQuery : IQuery { // Implementation } public class PickQuery : IQuery { // Implementation } 

然后,您可以更改Agency类以存储IQuery对象的实例,而不是(或除了) ClientDb对象之外:

 public class Agency { public IQuery Query { get; set; } } 

然后在初始化代码中(通常设置ClientDb属性),可以将实例设置为适当的IQuery实现:

 agency.Query = new PickQuery(); 

ADO.NET有一组通用类:DbCommand,DbConnection等……它们还实现了另一组通用接口:IDbCommand,IDbConnection等……

所以你可以使用它们,但最终可能会变得非常复杂。 您的解决方案的优势在于它非常易读。 另外,pick数据库可能没有任何ADO.NET提供程序……

PS:我会替换Type属性类型,而是使用枚举。

要编写更少的代码但提高可读性,可以使用代表为每个数据库切换到字典的语法代码级别。 这很容易扩展,并且非常易读。 考虑到更多function性方法,您可以获得类似的function

 void Query(Agency agency, Citation queryCitation) { Dictionary> QueryMap = new Dictionary> { { "SQL", QueryOracle}, { "PIC", QueryPic} }; queryCitation.AgencyCode = agency.AgencyCode; QueryMap[agency.ClientDb.Type](agency, queryCitation); } 

有两种OOP解决方案多态性和访问者模式 。