java - 更好的替代方法是使用 Void 作为可选参数

标签 java oop generics

我有一个接口(interface)指定方法,它采用通用类型作为用于创建 URL 的输入。

interface UrlGenerator<T> {

    String prepareUrl( T input );

}

有一种实现不需要参数。它对泛型类型 T 使用 Void。

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;
    }

}

我认为我的设计一定存在根本性的错误。

最佳答案

I think there must be something fundamentally wrong with my design.

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

基本上你有三个选择:

  • 坚持您当前的方法并在 Void 情况下显式传递 null

  • 向接口(interface)添加第二个(无参数)方法来处理 Void 情况,并使其调用带有null 的单参数方法。当 T 不是 Void 时,您的代码需要处理 null,但无论如何它都会处理。

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

就个人而言,选项 2 比选项 1 稍微好一些,但选项 3 可能会导致其他问题;例如该特定方法及其两个变体将阻碍在 T 类型的整个空间上进行多态方法调用。

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

关于java - 更好的替代方法是使用 Void 作为可选参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12179124/

相关文章:

c# - 将 B 添加到 List<A<object>>,其中 B 使用值类型实现 A

.net - 有机会合法投吗?

Java 泛型 - 实现和扩展

java - 构造函数不创建对象——Java

java - 查找两个日期之间天数的算法

java - 不同端口上的多个 Spring Boot 实例 - 登录/注销问题

c# - 使用哪些设计模式来实现该业务逻辑?

java - 接口(interface)引用变量

php - PHP 中的父类(super class)和子类

java - 线程中出现异常 "AWT-EventQueue-0"java.awt.HeadlessException