我想提出一个很好的方案:
困惑?请继续阅读并告诉我您对该解决方案的看法。
假设我希望服务能够根据任何类型的密钥提供任何类型的对象 从任何地方(数据库,文件等)。
为了一个良好的开端,让我们创建一个合适的界面:
public interface ObjectProvider<K, V> {
V provide(K key);
}
通过这种方式,我将能够提供任何类型的实现。 我想提供数据库和文件中的对象。
假设基于K提供V可以用相同的方法完成 DB逻辑,不管对象类型如何。所以我可以写一个通用的基类 用于数据库访问:
public class DBObjectProvider<K, V> implements ObjectProvider<K, V> {
public V provide(K key) {
V v = null;
//some common DB logic to get V based on K
return v;
}
}
实际上,从文件中获取对象也是对象类型独立的:
public class FileObjectProvider<K, V> implements ObjectProvider<K, V> {
public V provide(K key) {
V v = null;
//some common file reading logic to get V based on K
return v;
}
}
好的,到目前为止,我有两个通用类可以用来获得我想要的东西。
现在,我想使用其中一个通用实现来获取基于数据库中的String键的String对象。另外,我希望它使用Spring XML定义为bean。 我想没有办法在Spring XML中定义一个通用bean(我是对的吗?)所以我 将创建一个合适的类。我需要做的就是:
public class DBStringStringProvider extends DBObjectProvider<String, String> {
}
现在我可以将这个bean注入任何:
private ObjectProvider<String, String> objectProvider;
一切都很好,现在是关键部分。 我可以在很多方面使用我有用的DB String-String提供程序(嗯......好吧不是真的)。假设我想制作一个Web服务。 假设我想将DBStringStringProvider公开为CXF Web服务并对其进行测试。 问题是这样的Web服务的客户端代码如下所示:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(<INTERFACE>.class);
<INTERFACE> client = (<INTERFACE>) factory.create();
所以我需要一个DBStringStringProvider的非泛型接口,我没有它,因为它扩展了它的通用基类。
我可以做以下事情:
扩展ObjectProvider&lt; String,String&gt;与另一个接口:
@WebService
public interface StringStringProvider extends ObjectProvider<String, String> {
@WebMethod
String provide(String key);
}
另外,在通用基类已经实现的地方实现它:
public class DBStringStringProvider extends DBObjectProvider<String, String>
implements StringStringProvider {
}
我觉得实现基类已经引入的相同接口有点不合适。 但通过这种方式,我可以使用WS客户端:
factory.setServiceClass(StringStringProvider.class);
StringStringProvider client = (StringStringProvider) factory.create();
我的问题是:做我刚刚做的事情是一种好习惯吗?如果没有,还有其他办法吗?
这只是一种情况,在这种情况下,为某些东西设置非通用接口会很棒 已被定义为通用。
答案 0 :(得分:1)
我不愿批评所提问题中抽象程度的动机。为了界面的一致性和减少重复代码,这些场景不时出现。特别是Java和icky服务框架使这项任务变得比它需要的复杂得多;这种不必要的复杂性并不意味着原始设计是坏的。每天Java都让我因为无意义的冗长而引起我的注意。
我很高兴地确认,定义一个无偿的具体子接口是可以接受和通用的做法。您被迫采取此操作,因为您正在解决服务框架中的限制(不允许参数化接口)。
唯一需要关注的是你真的想在Java中使用 typedef 。我能做的最好的事情w.r.t. Java中的typedef会导致令人难以置信的丑陋构造,这会使得原始帖子中的评论者从他们对复杂性的厌恶判断出来,想要自己测量自己的眼睛。
我怀疑在实践中你会遇到任何问题,但总的来说psuedo-typedefs这样的例子会导致意外的痛苦。在一般情况下,当您创建接口T
的简单子接口S
时,很有可能使用T
代替S
,无论它适用于何处。 S
可能是一个冗长的参数化Java类表达式,例如,读取或输入的内容很麻烦,T
可能很好而且简短。但是对于方法/服务调用/构造函数参数,您仍然需要S
作为声明的类型,否则您可能会限制方法或类的有用性。一个人为的例子:
public interface Info extends Map< String, List< FooBar > > {}
public interface Service {
public Info doSomething( Info info );
}
Service
没有理由只接受Info
,因为Info
不向Map< String, List< FooBar > >
添加API;如上所述,doSomething的调用者不能将任何旧地图作为输入;他们必须以某种方式创建一个新的Info
并使用该地图的内容对其进行初始化,因为Java(几乎所有其他广泛使用的企业语言)都使用主格输入。