英文:
Interface to return Generic type
问题
我有一个返回Connection的接口。我已经改成了Object,因为我有时需要从Mongo返回Connection,有时需要返回MongoDatabase对象。
我的想法是将这个方法改成Object,像这样:
Object getConnnection(String uri);
这是一个不太好的设计吗?有没有改进这种方法的建议?非常感谢任何建议。
英文:
I have an interface that returns a Connection. I've changed to Object, because I need to return sometimes a Connection and sometimes a MongoDatabase object from Mongo.
My poor ideia was to change this method to Object, like this:
Object getConnnection(String uri);
Is a poor design? Any suggestion to improve this aproach? Thanks a lot for any suggestion.
答案1
得分: 1
I have an interface that returns a Connection. I've changed to Object because I need to return sometimes a Connection and sometimes a MongoDatabase object from Mongo. My poor idea was to change this method to Object, like this:
我有一个返回 Connection 的接口。我已经将其更改为 Object,因为我需要有时返回来自 Mongo 的 Connection,有时返回 MongoDatabase 对象。我的想法不太好,是将此方法更改为 Object,如下所示:
Object getConnnection(String uri);
Is a poor design?
这是一个较差的设计吗?
If the intended uses of this interface will require users to cast the return value, or otherwise do anything with it that depends on knowing or assuming whether it is a Connection
or a MongoDatabase
, then yes, it is a poor design.
如果该接口的预期用途需要用户对返回值进行类型转换,或者以其他方式处理它,这取决于知道或假设它是 Connection 还是 MongoDatabase,那么是的,这是一个较差的设计。
Also, getConnection
is a terrible name for a method that in fact might return something that is not a Connection
.
而且,getConnection
是一个糟糕的方法名称,因为实际上可能会返回不是 Connection
的东西。
Any suggestion to improve this approach?
有什么建议可以改进这种方法吗?
There are plenty of alternatives that would be better, but which one is best for you depends on how you want to use instances of this interface. Some of the more likely possibilities are:
有很多更好的替代方法,但哪一种对你最好取决于你想如何使用此接口的实例。以下是一些更有可能的选择:
-
give the interface separate methods for retrieving a
Connection
and for retrieving aMongoDatabase
. This is not great if individual instances cannot be expected to be able to do both, but even then it's better than the version presented in the question. -
为接口提供分开的方法,用于检索 Connection 和 MongoDatabase。如果不能期望单个实例能够同时执行这两个操作,那么这不是一个好方法,但即使如此,它也比问题中提出的版本更好。
-
provide a separate interface representing objects that can provide
MongoDatabase
s, with an appropriately-named method for that purpose. -
提供一个单独的接口,代表能够提供 MongoDatabase 的对象,并为此目的提供一个适当命名的方法。
-
put a method for retrieving a
MongoDatabase
(only) on a class implementing the interface, and make methods that need to be able to exercise thatgetMongoDatabase()
method require instances specifically of that class. Possibly create a sub-interface that specifies thegetMongoDatabase()
method. -
在实现接口的类上放置一个仅用于检索 MongoDatabase 的方法,并使需要能够使用该
getMongoDatabase()
方法的方法专门需要该类的实例。可能创建一个子接口,指定getMongoDatabase()
方法。 -
make the interface generic, parameterized by the type of object to which it provides access. For example:
-
使接口成为通用接口,通过提供访问的对象类型进行参数化。例如:
interface DatabaseAccessor<T> {
public T getDatabaseObject();
}
Each implementation would then be specific for Connection
s or MongoDatabase
s or some other similar thing. Other methods that want to consume these specify what flavor of DatabaseAccessor
they need via the type parameter.
然后,每个实现将具体针对 Connection、MongoDatabase 或其他类似的对象。希望使用这些方法的其他方法通过类型参数指定他们需要的 DatabaseAccessor 类型。
英文:
> I have an interface that returns a Connection. I've changed to Object,
> because I need to return sometimes a Connection and sometimes a
> MongoDatabase object from Mongo. My poor ideia was to change this
> method to Object, like this:
>
> Object getConnnection(String uri);
>
> Is a poor design?
If the intended uses of this interface will require users to cast the return value, or otherwise do anything with it that depends on knowing or assuming whether it is a Connection
or a MongoDatabase
, then yes, it is a poor design.
Also, getConnection
is a terrible name for a method that in fact might return something that is not a Connection
.
> Any suggestion to improve this aproach?
There are plenty of alternatives that would be better, but which one is best for you depends on how you want to use instances of this interface. Some of the more likely possibilities are
-
give the interface separate methods for retrieving a
Connection
and for retrieving aMongoDatabase
. This is not great if individual instances cannot be expected to be able to do both, but even then it's better than the version presented in the question. -
provide a separate interface representing objects that can provide
MongoDatabase
s, with an appropriately-named method for that purpose. -
put a method for retrieving a
MongoDatabase
(only) on a class implementing the interface, and make methods that need to be able to exercise thatgetMongoDatabase()
method require instances specifically of that class. Possibly create a sub-interface that specifies thegetMongoDatabase()
method. -
make the interface generic, parameterized by the type of object to which it provides access. For example,
interface DatabaseAccessor<T> { public T getDatabaseObject(); }
Each implementation would then be specific for
Connection
s orMongoDatabase
s or some other similar thing. Other methods that want to consume these specify what flavor ofDatabaseAccessor
they need via the type parameter.
答案2
得分: 1
除非你计划仅使用 toString
或 Object
上的其他几种方法,否则该类型没有用处。因此,客户端代码将不得不尝试向下转换以执行更有用的操作。因此,它通常被视为设计上的问题。我目前没有重构的副本,但据我记得,它描述了代码中的问题,并提出了更好的替代方案。
什么是更好的设计?这取决于上下文。接口首次存在的原因是什么?
您可以考虑遵循依赖反转原则,这意味着抽象应该由客户端代码定义,而不是由实现类定义。
由于您没有描述客户端代码的需求,很难建议更好的API。我建议查看客户端代码的要求,然后定义一个支持这些交互的类型(接口或基类)。然后从该方法返回该类型。
如果您不能这样做,和类型可能会有用。不幸的是,大多数面向对象的编程语言不本地支持和类型,但您可以使用访问者设计模式来实现它们。
英文:
Unless you plan to only use toString
or the other few methods available on Object
, that type isn't useful. Thus, client code will have to attempt to downcast in order to do something more useful with it. Thus, it's generally regarded as a design smell. I don't currently have my copy of Refactoring handy, but as far as I recall, it describes the code smell and suggests better alternatives.
What's a better design? This depends on context. Why does the interface exist in the first place?
You may consider following the Dependency Inversion Principle, which entails that abstractions should be defined by client code, and not by the implementing class.
Since you don't describe the needs of client code, it's difficult to suggest a better API. I'd suggest to look at the requirements that client code has, and then define a type (interface or base class) that supports those interactions. Then return that type from the method.
If you can't do that, a sum type could be useful. Unfortunately, most object-oriented languages don't support sum types natively, but you can implement them with the Visitor design pattern.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论