2012-08-29 64 views
3

我有一個接口指定方法,它將一個通用類型用作輸入,用於創建一個URL。使用Void作爲可選參數的更好選擇

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

你可以使用一個可變參數的簽名從一開始:'字符串prepareUrl(T. ..輸入);' –

+2

對我來說看起來像一個Twitter API客戶端:-)無論如何...在面向對象,操作不是由他們的名字來定義,而是由他們做什麼。在你的場景中,prepareUrl在不同的類中做不同的事情。解決方法是給兩個方法使用不同的名稱來區分它們的操作。 – 2012-08-29 13:34:27

回答

5

我認爲我的設計一定會有根本性的錯誤。

唯一錯誤的是您試圖混合一個參數方法和一個零參數方法。你不能用Java來做它......而不打開其他問題的大門。

基本上你有三個選擇:

  • 堅持你目前的做法,並明確通過null在虛空情況。

  • 向接口添加第二個(無參數)方法來處理Void情況,並使其與null一起調用一個參數方法。當T不是Void時,您的代碼需要應對null,但無論如何。

  • 重構接口,以便有兩個不同的接口,一個接口是String prepareUrl(),另一個接口是String prepareUrl(T),並將前者作爲特例類實現。

就個人而言,選項2稍好於選項1,但第三個選項可能會導致其他問題;例如具有兩個變體的特定方法將成爲在整個T類型空間上多態方法調用的障礙。

(可變參數是一個壞主意,因爲這將打開多個參數的門這可能是無意義的你的問題。)

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)); 
2

的問題是,如果真的SchedulePageUrlGenerator一個UrlGenerator。如果它有不同的論點,那麼我會認爲它不是。如果您有可選參數的接口,那麼我想你必須做的是這樣調用代碼:

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

這似乎是一個黑客。

這一切說,如果你有更多的方法來你的接口,只有prepareUrl(...)是不同的話,我看不出有什麼問題,在null傳遞作爲Void參數prepareUrl(...)。我想我會需要看到更多的調用框架,以瞭解如何生成參數以及爲什麼一個參數是這樣的問題。

另外一個替代方案,再次,如果你在你的界面更多的方法,是有有和無的說法準備方法:

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

然後你就可以扔UnsupportedOperationException這取決於由哪個支持實現。但是,如果你必須做一些類似instanceofif以上的陳述,那麼我認爲null的論點更好。