2013-02-01 57 views
1

前提條件:在我的項目中,我有兩個分別定義請求和響應的一般類型接口。處理請求以產生響應,因此每個響應都基於請求構建。處理器接口處理請求以構建相應的響應。補充泛型類型

代碼:請求和響應接口是:

interface Request<T1> 

interface Response<T2> 
分別

,其中T2T1代表通用請求和響應類型(我故意通過不同調用它們名稱爲清晰)。

現在,由於T2 請求,和T1 響應,因此上述碼發展到:

interface Request<T1 extends Response> 

interface Response<T2 extends Request> 

注意的是:請求和響應接口不共享任何繼承關係 - 以上代碼僅用於進行通信的是:請求僅使用某種其他類型(即響應)進行鍵入。

現在,考慮請求接口:由於響應被再次輸入,並且建立了一種請求的響應將被捆綁到原來的請求類型,因此,上面的代碼發展到:

interface Request<T1 extends Response<? extends Request<T1>>> 

和現在

interface Response<T2 extends Request<? extends Response<T2>> 

,處理器接口被定義爲:

interface Processor<R1 extends Request<R2>, R2 extends Response<R1>> { 
    R2 process(R1 request); 
} 

具體類:

要求執行:

class ConcreteRequest implements Request<ConcreteResponse> { 
    ConcreteResponse response; 
    ...` 
} 

響應實現:

class ConcreteResponse implements Response<ConcreteRequest> { 
    ConcreteRequest request; 
    ... 
} 

處理器實現:

class ConcreteProcessor implements Processor<ConcreteRequest, ConcreteResponse> { 
    ConcreteResponse process(ConcreteRequest request) { 
    ... 
    } 
} 

問題:上面的代碼是否過度設計?是否有簡化的方法來表示補充輸入輸出對象的元組?

+0

對不起,您能解釋一下這個嗎?'Request '爲什麼'T1''Request'會擴展'Response'類型? – vijay

+0

@Vijay:T1不是一個響應,它是泛型類型,它指示它最終會在處理後生成的響應...例如列表意味着一個包含字符串對象作爲其元素的列表......是你所詢問? – Neel

+0

通過'Request'和'Response'使用泛型,你會獲得什麼?一個簡單而具體的例子在這裏會有很長的路要走。 –

回答

1

除非我完全誤解了你的問題,否則你不會 - 也不應該 - 爲這類問題使用泛型。使用多態性和/或組合將會更合適。例如,如果您需要在響應中集成請求的副本(幾乎不必要但可以想象),那麼您可以在響應類中添加對請求對象的引用。

從技術上講,可以使用類型定義對Request對象的引用;然而,你不應該這樣做,因爲它永遠是一個對象(基類或派生子類),而不是某種隨着每個響應實例而改變的任意類。

可以使用通用的,當每個被引用對象的類型是完全不同的(例如,一個List <String>List<Request>:有一個StringRequest物體之間沒有子類的關係),或當使用多態性將是不夠的因爲你正在一個子類中定義一個或多個新的虛函數,這些虛函數不在超類中。

建設Response是基於一個Request因爲Request進行處理,以產生Response絕對不是要走的路和當前Processor接口是證明了這一點。

+0

謝謝你的答案。我理解你的觀點,爲什麼泛型不適用:泛型類型可能的類型之間沒有「子類化關係」,但爲什麼你認爲「建立響應基於請求......絕對不是去...處理器界面是對此的證明。「 - 是否導致任何反模式?如果你可以請解釋。謝謝! – Neel

+0

響應將在請求之後構建併發回的事實並不意味着這兩者之間存在分層的超類/子類關係。從面向對象的角度來看,響應和請求是屬於兩個不同類別的兩個不同的對象。他們可能會共享一些常見的函數,接口或其他元素(這一切都取決於您的代碼),但是您不應該將這些共享元素與函數混淆,回覆將作爲對請求的答覆發回。 – SylvainL

+0

你爲什麼認爲請求和響應共享一個繼承關係? (這是來自我的代碼片段的暗示嗎?如果是這樣,我正在更新一個筆記)事實上,我使用組合來保持一個在另一箇中的引用。唯一的繼承是用Request定義的泛型類型;這意味着請求通常與另一種類型的響應相關聯。 – Neel

1

我想你不需要在類型定義中鏈接RequestResponse。他們與Processor並列。是不是像

interface Requestable { 
    ... 
} 

class Request<T extends Requestable> { 
    ... 
} 

class Response<T extends Requestable> { 
    ... 
} 

class Processor<T extends Requestable> { 
    Response<T> process(Request<T> request) { 
     ... 
    } 
} 

足夠?其實我不確定你需要通用。

+0

感謝您的回覆。在你的代碼片段的上下文中,請求和響應不需要一般地輸入。 – Neel

0

有一個使用案例,它有一個有效的請求/響應(或好,至少是請求)。如果請求泛型包含響應類型,下面的調用是「類型安全」

public <messy define of T> T sendRequest(Request<T> request) 

現在,方法的用戶會看到「安全類型」請求 - 響應調用。我只是稱這只是「類型安全」,因爲該方法的實現可能需要將響應轉換爲T,所以ClassCastException在理論上是可行的,但在大多數情況下,它們將被視爲應用程序邏輯錯誤。

我不會把請求/響應的實際字段放在其他地方,只是使用泛型類型信息來進行「類型安全」的請求 - 響應調用。