2011-04-27 80 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。 这是处理抽象的最好方法吗?我认为这个模型是非常可扩展的......