2016-06-13 16 views
0

我有一個類的集合,稱它們爲Derived1, Derived2, ..., Derived6,每個類都是基類Base的子類。這些類是在第三方Java包中定義的。下面的OOP設計有更好的選擇嗎?

我正在寫一個類,將寫出這些對象的人類可讀的表示。我按如下方式處理了這個問題:定義方法String transform(Derivedi object),對於每個i=1,2,...,6String transform(Base object)

問題發生在例如Base obj = new Derived3(...)和我想計算obj的表示形式時。表達式transform(obj)調用帶有簽名String transform(Base)的方法,該方法必須調用「正確」方法(在這種情況下是具有簽名String transform(Derived3)的方法)。

方法String transform(Base object)委託人通過if (obj instanceof Derivedi)形式的條件語句對每個i=1,2,...,6工作到適當的方法。 (如果我有對包的控制權,我將在基類上有一個抽象方法String toReadable(),這對每個派生類都必須實現;不幸的是,在這種情況下我無法控制包)。

我不像這個解決方案一樣(很容易看出原因)。 String transform(Base)的這個實現有什麼替代方案?

+0

我不明白這個問題怎麼可能出現。你有沒有考慮重寫'toString()'方法?或者您所描述的類層次結構中的另一個簡單覆蓋?而不是別的需要參數的地方? – EJP

+0

這不是多態,多態性將調用所有對象上的相同方法(如您提到的toReadable()方法)。這裏有一個內置的Java機制,每個Class都有一個從Object繼承的toString()方法,可以爲特定於類的行爲重寫,也許給予您的類重寫它。如果不是,則必須求助於非OO解決方案,例如if-else序列。請記住,無論何時你有一個開關情況,或者在這種情況下,它是醜陋的if-else序列表親,你可以用你正在檢查的行爲值的映射替換它。 –

回答

1

您可以嘗試併爲每個班級提供變壓器(包含transform(...)的對象)。然後保持一張將變換器映射到這些類的映射(假設變換器本身是無狀態的)。

例子:

class Transformer { 
    Class<? extends Base> getTransformableClass() { ... } 
    String transform(Base obj){ 
    //check and cast obj to the actual type then create the string 
    } 
} 

Map<Class<?>, Transformer> transformers = ...; 
Transformer base = new BaseTransformer(); //the same for derived 
transformers.put(base.getTransformableClass(), base); 

注意與CDI /反射,你可以稍微做自動查找(即查找實現某個接口或具有一定的註釋進行註釋的所有類)。

然後使用它是這樣的:

public String transform(Base obj) { 
    //add null checks etc. 

    return transformers.get(obj.getClass()).transform(obj); 
}  

還應注意的是仿製藥可能有助於實現變壓器,但使用它們從地圖則會使一些鑄件/原始類型的必要,因爲你不知道實際的時你從地圖上得到的類型,即你作爲開發人員知道transformers.get(Derived1.class)應該返回一個能夠處理Derived1實例的變換器,但是編譯器不知道這一點,因此需要你處理並適當地進行轉換。

0

您可以使用getSimpleName()獲取類的名稱,並在名稱上使用switch語句。您仍然需要在transform(Base object)中完成這個授權,但會比幾個if語句和instanceof檢查更清晰。