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

发布于 2024-11-03 18:35:45 字数 442 浏览 0 评论 0原文

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

There is a part in my java code where I am extending a class from a library which I haven't written.

@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);
}

Now in this case how should I modify this code to make it scalable. There would be many more properties like location, dimension, etc. Now this model is instance of an abstract class AbsModel.

So every class implementing the AbsModel would have different properties. So the class architecture should be there, so that this part of code remains unchanged, no matter how many more model classes I add.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

仅冇旳回忆 2024-11-10 18:35:45

看起来您想在调用此方法(getPropertyValue)时对模型进行一些操作。我将在 ModelOperation 接口上创建一个 id 映射,定义如下:

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 实现上使用泛型,以避免对每个操作中的值进行强制转换。

It looks like you want to carry out some operation on the model when this method (getPropertyValue) is called. I would create a Map of id onto the interface ModelOperation defined as follows:

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

Then the map would be defines as follows:

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

Your extension class would then look like this:

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

For example, RenameOperation would be defined like this:

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

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

This allows you to support as many model operations as you like and means you don't have to change the extension class you have to write. The above is just an outline. You could use generics on the ModelOperation implementations to avoid the cast of the value in each one.

榕城若虚 2024-11-10 18:35:45

我想如果你可以依靠一些命名来帮助指导你的话,反思可能就是答案。

这不会很好,但想法是您将有一个可以反映类型并查找适当方法的方法。代码如下

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);
}

I guess reflection is probably the answer here if you can rely on some naming to help direct you.

It's not going to be nice, but the idea would be that you'd have a method that would reflect on the type and look up the appropriate method. The code 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);
}
十秒萌定你 2024-11-10 18:35:45

有多种方法可以做到这一点 - 尽管这取决于“可扩展”的含义(每秒能够处理大量请求或能够处理大量属性?):

  • 一种方法 - 如果您我们将按照您在代码中概述的路径进行操作,将那些经常使用的属性放在 if/then/else 块的顶部 - 因此它们的执行路径非常短。这将很好地“扩展”大量的请求,因为在实际执行该方法时不会花费太多时间(至少在大多数情况下!)
  • 另一种方式——这可以很好地扩展大量的属性并且易于维护代码,但执行时间会受到影响:有一个将属性名称映射到 setxxx() 方法名称的 Map,然后您可以在每次调用时使用反射在目标对象(在您的情况下为 id)上调用这些方法。扩展类的类只需提供 getMap() 方法,该方法将返回名称到 setter 方法的映射,该方法可以是静态成员并在类加载时初始化。
  • 将属性存储在 Map 中 - 在这种情况下 setName() 与 map.put( PROPERTY_RENAME, value) 相同

There are multiple ways of doing this -- though it depends on what do you mean by "scalable" (being able to cope with lots of requests per second or being able to cope with lots of properties?):

  • one way -- if you're going to go down the path you have outlined in your code is to have those properties that are used very often at the top of your if/then/else block -- so their execution path is very short. this would "scale up" well for lots of requests as not too much time is being spent in actually executing the method (in most cases at least!)
  • another way -- and this scales up well for lots of properties and easiness of maintaining the code but you will take a hit on execution time: have a Map that maps property names to setxxx() method names, then you can use reflection to invoke these methods on the target object (id in your case) on each call. Classes extended your class will only have to provide a getMap() method which will return the mapping name-to-setter method, which can be a static member and initialized on class load.
  • Store your properties in a Map -- in which case setName() is the same as map.put( PROPERTY_RENAME, value)
眼前雾蒙蒙 2024-11-10 18:35:45

由于在 Java 中函数不是一等公民,因此“好”路线将非常尴尬:定义一个枚举,上面每个常量(即每个属性)都有一个值,以及一个虚拟方法,例如 update(Object value< /code>,然后重写每个枚举中的方法来更新相应的属性。如果可以,将常量 PROPERTY_RENAME 本身重新定义为枚举。

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

Since in Java functions are not first class citizens, the "nice" route would be very awkward: define an enum with one value per each constant above (i.e. for each property), and a virtual method e.g. update(Object value, then override the method in each enum to update the corresponding property. If you can, redefine the constants PROPERTY_RENAME etc. themselves as enums. This still results in code bloat.

The other way is to use reflection. If you can use the same ids as the property names you want to update, you only need to invoke the setter for the property (as illustrated in other answers). Otherwise you may need to introduce a mapping from ids to property names.

我也只是我 2024-11-10 18:35:45

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

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

A version not using reflection, call the base class's implementation:

public Object getValue(Object id) {
  Object ret = super.getValue(id);
  if (ret == null) {
     // Subclass specific properties
  }
  return ret;
}
箜明 2024-11-10 18:35:45

解决这个问题的常见方法是使用像

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.
}

A common way around this is to use reflection like

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.
}
徒留西风 2024-11-10 18:35:45

我通过创建一个接口解决了这个问题。所以代码是。

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 ... }
}

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

I solved this issue by creating an interface. So the code is.

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

Rest of the classes were

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

So in this case every class has to handle it's own property setters.
Is this the best way to handle abstraction ? I think this model is very scalable ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文