首页 > 解决方案 > 如何使用接口/类似的东西来清理 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()调用,以及在 SubObject1 和 2 中具有唯一实现的getData()方法。

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

标签: javaoopinterfacecoding-stylecode-duplication

解决方案


你的问题说得不好,但我会尽量用提供的信息来回答。

首先,我会写一个抽象类。

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

现在我们可以根据需要在许多其他类中实现这个接口。假设你现在有两个。

    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 的孩子,并且可以为孩子拥有孩子,依此类推。

现在,在您的作家中,您可以只使用一种方法:

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

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


推荐阅读