【问题标题】:Avoid code duplication on child classes of an abstract class避免抽象类的子类代码重复
【发布时间】:2017-10-01 06:39:04
【问题描述】:

我正在开发一个旧的 Struts 应用程序,该应用程序具有通过填充 Excel 模板文件来创建 Excel 导出的抽象操作。

每个 Excel 导出操作都扩展了这个父类,并添加了自己的实现来填充 Excel 模板,并定义了自己的模板和输出文件名。

public abstract class ExcelExportAction extends BaseAction {
    protected abstract String getInputFilename();
    protected abstract String getOutputFilename();
    protected abstract HSSFWorkbook modifyWorkbook(HSSFWorkbook workbook, HttpServletRequest request);

    @Override
    protected final ActionForward run(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)
    throws Exception {

        Workbook workbook = new Workbook(getInputFilename());
        workbook = modifyWorkbook(workbook, request);
        addWorkBookToResponse(workbook, getOutputFilename());       

        return null;
    }
...
}

实现看起来像这样,这是 SonarQube“警告”代码重复的地方:

public class BudgetReportExcelAction extends ExcelExportAction {
    private static final String INPUT_FILENAME = "Report-Budget-Template.xls";
    private static final String OUTPUT_FILENAME = "Report-Customerbudget.xls";

    @Override
    protected String getInputFilename() {
        return INPUT_FILENAME;
    }
    @Override
    protected String getOutputFilename() {
        return OUTPUT_FILENAME;
    }
    @Override
    protected HSSFWorkbook modifyWorkbook(HSSFWorkbook workbook, HttpServletRequest request) {
        /* modify the workbook */
        return workbook;
    }
}

有什么方法可以避免重复吗?

【问题讨论】:

  • 您可以创建某种DefaultExcelAction 来扩展ExcelExport 并实现通用功能,然后让BudgetReportExcelAction(和其他子类)扩展DefaultExcelAction 而不是ExcelExport
  • 好吧,我在这里看不到任何重复...是的,您必须覆盖方法,但这就是 OOP 的重点。
  • SonarQube 可以,但正如其他 cmets 所述,这可能是一种偏执的配置......

标签: java oop design-patterns abstract-class


【解决方案1】:

这里没有答案:您的示例中没有“代码重复”。

重点是:您的抽象类驱动您的子类有一定的“布局”;但这就是使用抽象类的精髓

换句话说:这里没什么好担心的。

您正在遵循众所周知的“认可”模式;例如,通过在您的子类中很好地使用 @Override 注释。

一切顺利,祝你有美好的一天!

【讨论】:

  • 好吧,这只是 SonarQube 告诉我到处都是重复的代码。这次不得不忽略它,我想......谢谢!
  • 有人将您的 SonarQube 配置为偏执于代码重复。
  • C-:= 照顾。
  • 我们去 ;-)
【解决方案2】:

我在这里看到的代码中几乎没有任何代码重复,但如果你真的想“从石头中挤出水”,你可以在基类中添加一个构造函数,它接受输入文件名和输出 -文件名,并使每个派生类将其输入文件名和输出文件名传递给基类的构造函数。

【讨论】:

  • 我不能在这里采用构造方法,因为这些是 Struts 操作,据我所知,它们需要有一个空的构造方法。
  • 那么,你被困在调用可覆盖对象上。我认为这没什么大不了的。我们倾向于从几行及以上开始讨论代码重复。如果实际上正如您所说的使用 struts,那么对我来说,这将是永远不要使用 struts 并且不适用于需要使用 struts 的任何人的充分理由。
  • 你领先我一分钟;但你得到了我的支持 ;-)
最近更新 更多