3

我有一个接口指定方法,该方法将泛型类型作为输入,用于创建 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;
    }

}

我认为我的设计一定存在根本性的问题。

4

3 回答 3

5

我认为我的设计一定存在根本性的问题。

唯一错误的是您试图将单参数方法和零参数方法混为一谈。你不能在 Java 中做到这一点......不打开其他问题的大门。

基本上你有三个选择:

  • 坚持您当前的方法并明确传递nullVoid 案例。

  • 向接口添加第二个(无参数)方法以处理 Void 情况,并使其调用带有null. 您的代码需要处理nullwhen Tis not Void,但无论如何它确实如此。

  • 重构接口,以便有两个不同的接口,一个带有 a String prepareUrl(),另一个带有String prepareUrl(T),并将前者实现为特例类。

就个人而言,选项 2 略好于选项 1,但选项 3 可能会导致其他问题;例如,具有两个变体的特定方法将成为对整个T类型空间进行多态方法调用的障碍。

(可变参数是一个坏主意,因为这为多个参数打开了大门,这对您的问题可能毫无意义。)

于 2012-08-29T13:42:42.093 回答
2

问题是如果SchedulePageUrlGenerator真的UrlGenerator. 如果它有不同的论点,那么我认为它不是。如果您的界面有可选参数,那么我猜在调用代码中您必须执行以下操作:

// this is not a good pattern
if (urlGenerator instanceof SchedulePageUrlGenerator) {
    (SchedulePageUrlGenerator)urlGenerator.prepareUrl();
} else {
    urlGenerator.prepareUrl(...);
}

这似乎是一个黑客。

综上所述,如果您的接口有更多方法并且只有prepareUrl(...)不同的方法,那么我null认为VoidprepareUrl(...). 我想我需要查看更多调用框架来了解您如何生成参数以及为什么null参数是这样一个问题。

如果您的接口中有更多方法,另一种选择是同时使用带参数和不带参数的准备方法:

String prepareUrl( T input );
String prepareUrlNoInput();

UnsupportedOperationException然后你可以根据哪个实现支持哪个抛出。但同样,如果你必须做类似上述instanceof if陈述的事情,那么我认为这个null论点更好。

于 2012-08-29T13:36:35.250 回答
1

您似乎希望为不同的实现评估不同数量的参数。

最接近这一点的是使用可变参数

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));
于 2012-08-29T13:36:34.860 回答