2011-11-18 78 views
2

這裏我已經有了一些代碼來將內核模型「轉移」到外部插件的「輸出」模型。爲此,我創建了基於傳遞的OldConnection的具體子類型的新實例,並將舊實例傳遞給構造函數,這樣我就可以輕鬆地爲getter和setter維護內部數據。在Java中將內核模型轉換爲輸出模型

因此,OldIncoming,OldOutgoing和OldExpected是OldConnection的子類型。 MyNewIncoming,MyNewOutgoing和MyNewExpected是MyNewConnection的子類型。不幸的是,我不能改變內核模型,我需要構造函數中的具體類型。

代碼看起來很醜陋,但我只是找不到更好的解決方案,任何想法?

private MyNewConnection createIConnectedSubtypeInstance(OldConnection connection) { 

    if (connection instanceof OldIncoming){ 
     return new MyNewIncoming((OldIncoming) connection); 
    } 
    if (connection instanceof OldOutgoing){ 
     return new MyNewOutgoing((OldOutgoing) connection); 
    } 
    . 
    . 
    . 
    if (connection instanceof OldExpected){ 
     return new MyNewExpected((OldExpected) connection); 
    } 

    return new MyNewConnection(connection); 
} 

回答

1

另一種方法是一堆重載方法,就像這樣:

private MyNewIncoming createIConnectedSubtypeInstance(OldIncoming connection) { 
    return new MyNewIncoming(connection); 
} 

然而,這隻能在調用方知道是什麼類型的connection,否則你不得不依靠這些instanceof檢查。

在這種情況下,你也可以有一些映射OldClass->的NewClass和使用反射來創建實例,但我懷疑,除非你需要一個映射巨大量,這將是值得冒這個險。

實施例:

Map<Class<? extends OldConnection>, Class<? extends NewConnection>> mapping; //initializing is up to you 

public NewConnection createIConnectedSubtypeInstance(OldConnection connection) { 
    try { 
    Class<? extends NewConnection> subtype = mapping.get(connection.getClass()); 
    return subtype.getConstructor(connection.getClass()).newInstance(connection); 
    } catch(Exception e) { //you might want to catch the more specific types 
    //handle appropriateley 
    } 
} 

注意,這依賴於類的connection被直接映射。如果您映射超類,則可能必須檢查那些沒有找到實際類connection的映射。

此外,這依賴於新實例的構造函數來接受映射類類型的一個參數。

1

你可以超載工廠方法:

OldIncoming a; 
... 
MyNewConnection b = createIConnectedSubtypeInstance(a); // will return MyNewIncoming 

private MyNewConnection createIConnectedSubtypeInstance(OldIncoming conn) { 
    return new MyNewIncoming(conn); 
} 

private MyNewConnection createIConnectedSubtypeInstance(OldOutgoing conn) { 
    return new MyNewOutgoing(conn); 
} 
... 

正如托馬斯在他的回答指出,這將只有當你調用這些方法與正確的靜態類型的工作由於重載使用靜態綁定,因此在這種情況下不能使用OldConnection。如果這不是您的選擇,那麼您會在某個時刻停止執行instanceof。

0

您可以將包裝的創建移動到OldConnection及其派生類。在OldConnection,與

public MyNewConnection createNewConnectiom() { 
    return MyNewIncoming(this); 
} 

定義的方法

public MyNewConnection createNewConnectiom() { 
    return MyNewConnection(this); 
} 

OldIncoming覆蓋和OldExpected覆蓋與

public MyNewConnection createNewConnectiom() { 
    return MyNewExpected(this); 
} 

這樣,你就擺脫了分公司和鑄件中。

+0

如果我理解正確,他不能更改OldConnection代碼,這可能是爲什麼他首先需要MyNewConnection包裝。 – pushy

+0

你是對的,我錯過了。 +1爲您的答案 – MartinZ