如何使这部分代码可扩展,

时间:2011-04-27 13:05:15

标签: java oop design-patterns

我的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的每个类都有不同的属性。所以类架构应该存在,所以无论我添加多少个模型类,这部分代码都保持不变。

7 个答案:

答案 0 :(得分:1)

当调用此方法(getPropertyValue)时,您似乎希望对模型执行某些操作。我将在如下定义的接口ModelOperation上创建一个id的Map:

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实现上使用泛型来避免在每个实现中转换值。

答案 1 :(得分: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.
}

答案 2 :(得分: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);
}

答案 3 :(得分:0)

有多种方法可以做到这一点 - 虽然这取决于“可扩展”是什么意思(能够应对每秒的大量请求或能够处理大量属性?):

  • 一种方式 - 如果您要沿着您在代码中列出的路径走下去,那么在if / then / else块的顶部经常使用那些属性 - 所以它们的执行路径很短。对于大量请求,这会“扩大”,因为在实际执行方法时花费的时间不多(至少在大多数情况下!)。
  • 另一种方式 - 这对于很多属性和维护代码的容易程度都很好,但是你会对执行时间产生影响:有一个Map将属性名称映射到setxxx()方法名称,那么你可以使用反射在每次调用时在目标对象(在您的情况下为id)上调用这些方法。类扩展你的类只需提供一个getMap()方法,该方法将返回映射名称到setter方法,该方法可以是静态成员并在类加载时初始化。
  • 将您的属性存储在Map中 - 在这种情况下,setName()与map.put(PROPERTY_RENAME,value)相同

答案 4 :(得分:0)

由于在Java函数中不是一等公民,所以“好”的路径会非常笨拙:定义一个枚举,每个常量上面有一个值(即对于每个属性),以及一个虚拟方法,例如: update(Object value,然后覆盖每个枚举中的方法以更新相应的属性。如果可以,请将常量PROPERTY_RENAME等自己重新定义为枚举。这仍然导致代码膨胀。

另一种方法是使用反射。如果可以使用与要更新的属性名称相同的ID,则只需调用属性的setter(如其他答案中所示)。否则,您可能需要引入从ids到属性名称的映射。

答案 5 :(得分:0)

不使用反射的版本,调用基类的实现:

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

答案 6 :(得分: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 ... }
}

所以在这种情况下,每个类都必须处理它自己的属性设置器。 这是处理抽象的最佳方法吗?我认为这个模型非常具有可扩展性......