如何使用 interface/something 类似于清理 Java 中的重复代码

How to use an interface/something similar to clean up duplicate code in Java

我有输出函数,可以将不同对象的数据输出到它们对应的文件中。这些函数中的大多数都遵循相同的模式,唯一的区别是所使用的对象以及扩展所使用的对象的固有方法。

我将 'obj' 传递给所有写入函数,在每个单独的写入函数中,我们调用不同的 'obj.get...' 函数来获取不同的对象以从中获取数据并输出。

我的输出函数是这样调用的:

for (Object obj : objects) {
    writer.writeSubOject1(obj, dir, "subObject1.csv", true);
    writer.writeSubOject2(obj, dir, subObject2.csv, true);
    ....
}

写入函数的代码:

public class Writer{

public void writeSubOject1(Object obj, File dir, String filename, Boolean append) {
    ArrayList<SubObject1> subObject1 = obj.getSubObject1();
    try {
        log.info("writing " + filename + "...");
        ArrayList<String[]> so1Data = SubObject1.getData(subObject1);
        final File out = CreateFileObject(dir, filename);
        writeCsv(so1Data, out, append);
    } catch (Exception e) {
        log.info("Error in writeSubOject1");
        log.error(e);
        e.printStackTrace();
    }
}

public void writeSubOject2(Object obj, File dir, String filename, Boolean append) {
    ArrayList<SubObject2> subObject2 = obj.getSubObject2();
    try {
        log.info("writing " + filename + "...");
        ArrayList<String[]> so2Data = SubObject2.getData(subObject2);
        final File out = CreateFileObject(dir, filename);
        writeCsv(so2Data, out, append);
      } catch (Exception e) {
        log.info("Error in writeSubOject2");
        log.error(e);
        e.printStackTrace();
    }
}
}

您可以看到这两种方法之间的唯一区别是 obj.getSubObjectX() 调用和 getData() 方法,它在 SubObject1 和 2 中具有独特的实现。

是否有更好的方法来消除重复代码?

你的问题提得不好,我会根据提供的信息尽量回答。

首先,我会写一篇摘要class。

public abstract class WritableObject {
    List<WritableObject> children = new ArrayList<>();
    public abstract  List<String> getDataAsStringList();
    List<WritableObject> getChildren() {
        return this.children;
    }
    
    public void addChild(WritableObject wo) {
        children.add(wo);
    }
}

现在我们可以根据需要在任意多的其他 class 中实现此接口。假设您现在有两个。

    public class WritableObjectOne extends WritableObject {

    @Override
    public List<String> getDataAsStringList() {
        return Arrays.asList(""); // here the object returns it's String representation
    }
}

public class WritableObjectTwo extends WritableObject {

    @Override
    public List<String> getDataAsStringList() {
        return Arrays.asList(""); // here the object returns it's String representation
    }
}

现在,最好的部分是您可以随意组合。您可以拥有任何 WritableObject 的 children,并且可以拥有 child 的 children,依此类推。

现在,在您的编写器中,您只能使用一种方法:

public class Writer {
    public void writeSubOject(WritableObject obj, File dir, String filename, Boolean append) {
        List<WritableObject> children = obj.getChildren();
        try {
            log.info("writing " + filename + "...");
            List<String> data = new ArrayList<>();
            for (WritableObject child:children) {
                data.addAll(child.getDataAsStringList());
            }
            final File out = CreateFileObject(dir, filename);
            writeCsv(data, out, append);
        } catch (Exception e) {
            log.info("Error in writeSubOject1");
            log.error(e);
            e.printStackTrace();
        }
    }
}

同样,也许这不是您想要的(我觉得返回字符串列表的方式很奇怪),但它至少应该可以帮助您找到正确的解决方案。

创建私有方法

writeSubOject(ArrayList<String[]> soData, File dir, String filename, Boolean append) {
   try {
        log.info("writing " + filename + "...");
        final File out = CreateFileObject(dir, filename);
        writeCsv(soData, out, append);
      } catch (Exception e) {
        log.info("Error in writeSubOject");
        log.error(e);
        e.printStackTrace();
    }
}

然后在你的public方法中

public void writeSubOject1(Object obj, File dir, String filename, Boolean append) {
    ArrayList<SubObject1> subObject1 = obj.getSubObject1();
    ArrayList<String[]> so1Data = SubObject1.getData(subObject1);
    writeSubOject(so1Data,dir,filename,append);
}

public void writeSubOject2(Object obj, File dir, String filename, Boolean append) {
    ArrayList<SubObject2> subObject2 = obj.getSubObject2();
    ArrayList<String[]> so2Data = SubObject2.getData(subObject2);
    writeSubOject(so2Data,dir,filename,append);
}