我有一个接口指定方法,它将泛型类型作为输入,用于创建URL。
interface UrlGenerator<T> {
String prepareUrl( T input );
}
有一个实现不需要参数。它使用Void作为泛型类型T.
class StaticUrlGenerator implements UrlGenerator<Void> {
private final String url;
public StaticUrlGenerator( String url ) {
this.url = url;
}
@Override
public String prepareUrl( Void nothing ) {
return url;
}
}
StaticUrlGenerator使用起来很难,因为它需要null作为prepareUrl
方法的参数。
我可能会丢失input
参数:
interface UrlGenerator<T> {
String prepareUrl( T input );
}
现在我必须以其他方式(在构造函数中)将所需的输入传递给实现类。这样我就失去了类的无状态特性,每次我想改变输入时,我都必须用不同的构造函数参数重新创建它。
class SchedulePageUrlGenerator implements UrlGenerator {
public static final String QUERY_STRING_BASE = "?from=";
private final String showingBaseUrl;
private final LocalDate date;
public SchedulePageUrlGenerator( String showingBaseUrl, LocalDate date ) {
this.showingBaseUrl = showingBaseUrl;
this.date = date;
}
@Override
public String prepareUrl() {
DateTimeFormatter fmt = DateTimeFormat.forPattern( "yyyy-MM-dd" );
String dateStr = fmt.print( date );
return showingBaseUrl + QUERY_STRING_BASE + dateStr;
}
}
我认为我的设计肯定存在根本性的错误。
答案 0 :(得分:5)
我认为我的设计肯定存在根本性的错误。
唯一不对的是你试图混合一个参数方法和一个零参数方法。你不能用Java做到这一点......没有打开其他问题的大门。
基本上你有三个选择:
坚持使用您当前的方法并在Void案例中明确传递null
。
向接口添加第二个(无参数)方法来处理Void案例,并使用null
调用一个参数方法。当null
不是T
时,您的代码需要应对Void
,但无论如何都要做到这一点。
重构接口,以便有两个不同的接口,一个带有String prepareUrl()
,另一个带有String prepareUrl(T)
,并将前者作为特殊案例类实现。
就个人而言,选项2略好于选项1,但第3选项可能会导致其他问题;例如具有两个变体的特定方法将阻碍T
类型的整个空间上的多态方法调用。
(Varargs是一个坏主意,因为这为多个参数打开了大门,这可能对你的问题毫无意义。)
答案 1 :(得分:2)
问题是,SchedulePageUrlGenerator
确实 是UrlGenerator
。如果它有不同的论点,那么我认为它不是。如果您的接口有可选参数,那么我想在调用代码中您必须执行以下操作:
// this is not a good pattern
if (urlGenerator instanceof SchedulePageUrlGenerator) {
(SchedulePageUrlGenerator)urlGenerator.prepareUrl();
} else {
urlGenerator.prepareUrl(...);
}
这似乎是一个黑客攻击。
所有这些都说,如果你的接口有更多的方法,只有prepareUrl(...)
不同,那么我认为将null
作为Void
参数传递给{{1}没有问题}}。我想我需要看到更多的调用框架,以了解如何生成参数以及为什么prepareUrl(...)
参数是一个问题。
另一个替代方案,如果你的界面中有更多方法,那就是两个有和没有参数准备方法:
null
然后你可以抛出String prepareUrl( T input );
String prepareUrlNoInput();
,具体取决于哪个实现支持哪个。但同样,如果您必须执行上述UnsupportedOperationException
instanceof
语句之类的操作,那么我认为if
参数更好。
答案 2 :(得分:1)
您似乎想为不同的实现重复不同数量的参数。
最接近你的是使用varargs
interface UrlGenerator<T> {
String prepareUrl(T... input );
}
// can use
System.out.println(new StaticUrlGenerator("url").prepareUrl());
//or
System.out.println(new StaticUrlGenerator("url").prepareUrl(null));