我怎样才能更好地设计这个? (避免使用面向对象设计的 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 的对象。我正在使用遗留数据库系统,并将其部分重构为代码库。)显然,我可以在这里做一些不同的事情,这样我就不会具有相同输入的不同数据库查询不需要重复的函数。它应该只根据代理对象知道是使用 Oracle 数据库还是 Pick 数据库连接。 (如果您从未听说过 Pick 数据库,那么在我开始在这里工作之前我也没有听说过。我们通过 HTTP 请求对其进行查询,因此它不是 SQL。)
我应该创建一个接口,例如称为“ClientDbConnection” ”然后创建两个实现该接口的类,将查询数据库的代码移至这些类,然后用“agency.clientDb.Query(queryCitation)”之类的内容替换整个函数?我想我在这里大声思考,但对此的任何意见将不胜感激。
I know a little bit about Object Oriented design, but I'm not sure how to go about using those principles in my code. Here's what I'm working on:
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;
}
}
(Most of these are objects from NHibernate. I'm working with a legacy database system and am refactoring parts of it into a code library.) Clearly, I could do something differently here so that I don't need duplicate functions for different database queries that have the same input. It should just know based off of the agency object whether to use an Oracle database or a Pick database connection. (If you've never heard of a Pick database, well I hadn't either until I started working here. We make queries to it through HTTP requests, so it's not SQL.)
Should I make an interface, for example called "ClientDbConnection" and then make two classes that implement that interface, move the code to query the database to those and then have something like "agency.clientDb.Query(queryCitation)" replace this whole function? I guess I'm thinking aloud here, but any input on this would be appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Agency 是你控制的类吗?如果是这样,请执行以下操作:
在您的 Agency 类中,您可以有
然后有一个 SqlDb 类,例如:
然后此代码:
变为
因为继承,它将知道 ClientDb 有一个 GenericDb 基类。它会通过ClientDb参数的类型知道是否应该运行SqlDb或PicDb或Oracle等。
Is Agency a class you control? If so do something like this:
In your Agency Class, you could have
Then have a SqlDb class like:
Then this code:
becomes
Because of inheritance, it will know that ClientDb has a base class of GenericDb. It will know by the type of the ClientDb parameter whether it should run the SqlDb or the PicDb or Oracle etc.
您可能希望在此处实施策略模式。基本上, switch 语句中的每个可能的“类型”都将成为实现相同接口的自己的类。
应用策略模式
然后,您可以使用以“type”值作为参数的工厂方法。该方法将返回正确的类(其返回类型是上面提到的接口)。
You will likely want to implement the strategy pattern here. Basically, each of your possible "types" in your switch statement would become a class of its own that implements the same interface.
Applying the Strategy Pattern
You can then use a factory method that takes a "type" value as its parameter. That method would return the correct class (its return type is the interface mentioned above).
我会重构以利用接口。我可能会这样做:
然后,您可以更改 Agency 类来存储
IQuery
对象的实例,而不是(或除了)ClientDb
对象:并且然后在初始化代码中(通常设置
ClientDb
属性),您可以将实例设置为适当的IQuery
实现:I would refactor to take advantage of an interface. I would probably make it something like:
You could then change the Agency class to store an instance of an
IQuery
object rather than (or in addition to) theClientDb
object:And then in your initialization code (where you would normally set the
ClientDb
property), you could set the instance to the appropriateIQuery
implementation:要编写更少的代码但提高声明性代码级别的可读性,您可以切换到带有每个数据库委托的字典。它可以很容易地扩展并且非常可读。考虑到更实用的方法,你会得到类似的东西
To write less code but improve readability the the level of declaritive code you can swith to a dictionary with delegates for each database. That can easily be extended and is very readable. With that more functional approach in mind you get something like
ADO.NET 有一组通用类:DbCommand、DbConnection 等...还实现了另一组通用接口:IDbCommand、IDbConnection 等...
因此您可以使用它们,但最终可能会变得相当复杂。您的解决方案的优点是它非常具有可读性。另外,也许选择数据库没有任何 ADO.NET 提供程序...
PS:不过,我会替换 Type 属性类型,并使用枚举代替。
ADO.NET has a set of generic classes: DbCommand, DbConnection, etc... that also implement another set of generic interfaces: IDbCommand, IDbConnection, etc...
So you could use them, but it may become quite complicated in the end. The advantage of your solution is it's very readable. Plus maybe the pick database does not have any ADO.NET provider...
PS: I would replace the Type property type though, and use an enum instead.
有两种OOP解决方案多态性和访客模式。
There are two OOP solutions polymorphism and Visitor pattern.