我怎样才能设计得更好?(在面向对象的设计中避免切换语句)
本文关键字:面向对象的 语句 更好 | 更新日期: 2023-09-27 17:52:42
我对面向对象设计有一点了解,但我不确定如何在我的代码中使用这些原则。下面是我正在做的:
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的对象。我正在使用一个遗留数据库系统,并将其部分重构为代码库。)显然,我可以在这里做一些不同的事情,这样我就不需要为具有相同输入的不同数据库查询使用重复的函数。它应该根据代理对象知道是使用Oracle数据库还是Pick数据库连接。(如果你从未听说过Pick数据库,那么我在这里工作之前也没有听说过。我们通过HTTP请求对它进行查询,所以它不是SQL。)
我是否应该创建一个接口,例如称为"ClientDbConnection",然后创建两个实现该接口的类,将查询数据库的代码移动到这些类,然后使用"agency.clientDb.Query(queryCitation)"之类的东西替换整个函数?
代理是你控制的类吗?如果是,执行如下操作:
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);
}
由于继承,它将知道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
}
你可以改变代理类来存储一个IQuery
对象的实例,而不是(或者除了)ClientDb
对象:
public class Agency
{
public IQuery Query { get; set; }
}
然后在你的初始化代码中(你通常会设置ClientDb
属性),你可以设置实例到适当的IQuery
实现:
agency.Query = new PickQuery();
要编写更少的代码,但要提高声明性代码级别的可读性,您可以为每个数据库切换到带有委托的字典。它可以很容易地扩展,并且可读性很强。考虑到这种更实用的方法你会得到像
这样的东西void Query(Agency agency, Citation queryCitation)
{
Dictionary<string, Action<Agency, Citation>> QueryMap = new Dictionary<string, Action<Agency, Citation>>
{
{ "SQL", QueryOracle},
{ "PIC", QueryPic}
};
queryCitation.AgencyCode = agency.AgencyCode;
QueryMap[agency.ClientDb.Type](agency, queryCitation);
}
ADO。. NET有一组通用类:DbCommand, DbConnection等。还实现了另一组通用接口:IDbCommand, IDbConnection等…
所以你可以使用它们,但最后可能会变得相当复杂。你的解决方案的优点是可读性很强。另外,也许pick数据库没有任何ADO。净提供者……
PS:我将替换Type属性类型,并使用enum代替。
有两种OOP解决方案:多态性和访问者模式。