需要帮助重构一些重复的Java代码.接口或泛型或其他解决方案



我有一些数据对象,例如TaskResource等。

这些对象保存域数据,例如

public class Task{
   private int Id;
   private String taskName;
.......
  //getters and setters here
//in addition they have a special method dynamically to get values i.e. There is a reason for this
         public static String runGetter(Task task, String getter) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
                for (Method method : task.getClass().getMethods()) {
                    if (method.getName().toLowerCase().equalsIgnoreCase(getter.toLowerCase())) {
                        if (method.getReturnType().isPrimitive()) {
                            StringBuilder sb = new StringBuilder();
                            sb.append(method.invoke(task));
                            return sb.toString();
                        }
                        if (method.invoke(task) != null) {
                            return method.invoke(task).toString();
                        }
                    }
                }
                return null;
            }
        }
}

现在我有一些方法可以获取这些对象并将它们写入流

例如

public class WriterUtil{
    public void write(Task task, File outputFile){
    //write the task object out.

}

public void write(资源资源,文件outputFile){//写出资源对象}

        ....

}

write方法调用另一个方法从对象中获取数据,如下所示。(是的,它可以提高效率,但这不是我问题的核心)

public class WriterUtil {
.....
    public static String extractLine(Task task, LinkedHashMap<String, String> columns, String delimiter) throws IllegalAccessException,
                IllegalArgumentException, InvocationTargetException {
            StringBuilder sb = new StringBuilder();
            Iterator<String> itr = columns.keySet().iterator();
            while (itr.hasNext()) {
                String getter = "get" + itr.next();
                String value = Task.runGetter(task, getter);
                if (value == null)
                    value = "";
                sb.append(value + delimiter + " ");
            }
            return sb.toString().substring(0, sb.lastIndexOf(delimiter)).trim();
        }
......

}

我的主要问题是,在上面描述的场景中,我发现自己为每个域对象编写了相同的代码,例如

public void write(任务任务,文件outputFile)public void write(资源资源,文件outputFile)//等等。。。。

我对extractLine重复同样的操作。正如你所看到的,我正在为每个域对象复制相同的代码。其中唯一变化的是实际的域对象。这些方法对每个域对象执行完全相同的操作。

我的问题是;如果我要重构这些方法,并分别编写一个方法应用于每个域对象,那么我的最佳选择是什么。

  1. 我应该让域对象实现一个接口吗?这似乎相当麻烦,我不确定这是正确的做法
  2. 我可以使用仿制药吗?我认为这可能是最好的做法,但我对如何生成(这是一个词吗?)我的域对象和这些常见方法的经验非常有限。有人能对我的上述代码进行重写吗?他们将如何将其修改为通用代码
  3. 我还有第三种选择吗

将反射代码移动到实用程序类型中,并将签名更改为:

public static String runGetter(Object bean, String getter)

方法内部根本没有使用Task类型。

同样,这里需要Task类型的唯一原因是其他调用需要它:

public static String extractLine(Object bean, Map<String, String> columns,
                                                                String delimiter)

您需要使用一个接口;泛型不能在这里使用(您可以在C++中使用模板,但不能在Java中使用)。

如果不希望对象实现接口,可以为每个域类创建辅助对象;那些助手对象将实现一个具有extractLine()函数的接口:

class TaskExtractLine implements IExtractLine
{
  public TaskExtractLine(Task task)
  {
    this.task = task;
  }
  public String extractLine(LinkedHashMap<String, String> columns, String delimiter)
      throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
  {
    return WriterUtil.extractLine(task, columns, delimiter);
  }
  private Task task;
}

然后,您将得到这样的写函数:public void write(IExtractLine extractLineHelper, File outputFile),并将其调用为:write(new TaskExtractLine(task), outputFile)

最新更新