2011-04-27 78 views
2

在我的java代碼中有一部分是從一個我沒有寫過的庫中擴展一個類。如何使這部分代碼具有可伸縮性,

@override 
public Object getPropertyValue(Object id) { 
    if(id.equals(model.PROPERTY_RENAME)) 
     model.setName((String)value); 
    else if(id.equals(model.PROPERTY_COLOUR)) 
     model.setColor((Color)value); 
} 

現在在這種情況下,我應該如何修改此代碼以使其具有可伸縮性。將會有更多的屬性,如位置,尺寸等。現在這個模型是抽象類的實例AbsModel

因此,執行AbsModel的每個類將具有不同的屬性。所以類架構應該在那裏,以便這部分代碼保持不變,無論我添加多少模型類。

+3

這是一個吸氣或二傳手嗎?方法名稱表示getter,但正文使用未定義的「值」表示setter。 – 2011-04-27 13:10:38

回答

0

解決這個常見的方法是使用反射像

public Object getValue(IdType id) { 
    Method getter = model.getClass().getMethod("get" + id); 
    return getter.invoke(model); // throws Exceptions. 
} 

OR

public void setValue(IdType id, Object value) { 
    Method setter = model.getClass().getMethod("set" + id, value.getClass()); 
    setter.invoke(model, value); // throws Exceptions. 
} 
+0

不知道你可以做到這一點。涼! – Yossale 2011-04-27 13:15:59

0

我猜反射可能是答案在這裏,如果你可以依靠一些命名,以幫助引導您。

這不會很好,但主意是你會有一種方法反映類型並查找適當的方法。 belwo代碼

public Object setPropertyValue(Object id) { 
    String className = id.getClass().getSimpleName(); 

    // Hope that the method is called set<CLASS> and takes a single parameter that is the class 
    Method method = model.class.getMethod("set" + className, id.getClass()); 

    // Invoke the method (TODO deal with all of the exceptions) 
    method.invoke(model, id); 
} 
0

有這樣做的多種方式 - 儘管它取決於你的意思是「可擴展」(能夠應付大量的每個請求做第二或能夠應付大量的屬性?):

  • 一種方法 - 如果你打算沿着你在代碼中描述的路徑走下去,那麼你的if/then/else的頂部會經常使用這些屬性塊 - 所以他們的執行路徑很短。這對於大量的請求來說會「擴大」,因爲沒有太多的時間花在實際執行該方法上(在大多數情況下至少是!)
  • 另一種方式 - 這可以很好地擴展很多屬性和易用性維護代碼,但是你會對執行時間產生影響:有一個映射將屬性名稱映射到setxxx()方法名稱,然後你可以在每次調用時使用反射來調用目標對象上的這些方法(在你的案例中是id) 。擴展你的類的類只需要提供一個getMap()方法,該方法將返回映射的name-to-setter方法,該方法可以是一個靜態成員並在類加載時初始化。
  • Store中的地圖屬性 - 在這種情況下的setName()是一樣的map.put(PROPERTY_RENAME,值)
0

由於Java函數不是一等公民,在「好」路線會非常尷尬:定義一個枚舉值,每個常量上面有一個值(即每個屬性),以及一個虛擬方法,例如update(Object value,然後重寫每個枚舉中的方法來更新相應的屬性。如果可以的話,重新定義常量PROPERTY_RENAME等自己作爲枚舉。這仍然導致代碼膨脹。

另一種方法是使用反射。如果您可以使用與要更新的屬性名稱相同的id,則只需調用該屬性的setter(如其他答案所示)。否則,您可能需要引入從ID到屬性名稱的映射。

0

不使用反射一個版本,調用基類的實現:

public Object getValue(Object id) { 
    Object ret = super.getValue(id); 
    if (ret == null) { 
    // Subclass specific properties 
    } 
    return ret; 
} 
1

它看起來像你想進行一些操作上的模型時,這種方法(getPropertyValue)被調用。我想創建一個映射的id到定義爲接口ModelOperation如下:

public interface ModelOperation { 
    void operate(Object value); 
} 

然後,地圖會定義如下:然後

map.put(model.PROPERTY_RENAME, new RenameOperation(model)); 

您的擴展類是這樣的:

@Override 
public Object getPropertyValue(Object id) { 
    map.get(id).operate(model); 
    // etc... 
} 

例如,RenameOperation可以這樣定義:

public class RenameOperation implements ModelOperation { 
    public RenameOperation(Model model) { 
     // etc... 
    } 

    public void operate(Object value) { 
     model.setName((String)value); 
    } 
} 

這允許您支持儘可能多的模型操作,並且意味着您不必更改需要編寫的擴展類。以上只是一個提綱。您可以在ModelOperation實現上使用泛型,以避免在每個實例中轉換值。

0

我通過創建接口解決了這個問題。所以代碼是。

public interface IModel 
{ 
    public void setProperty(String propertyName); 
} 

類的其餘

public class HelloModel implements IModel 
{ 
     public void setProperty(String propertyName) 
     { code for handling the properties goes here ... } 
} 

因此,在這種情況下,每個類都有來處理它自己的屬性setter。 這是處理抽象的最好方法嗎?我認爲這個模型是非常可擴展的......