Reputation: 1262
I'm working on an old Struts application which has an abstract action to create Excel exports by filling Excel template files.
Each Excel export action extends this parent class and adds its own implementation for filling the Excel template and defines its own template and output filename.
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;
}
...
}
Implementations are looking like this and this is where the code duplication is "warned" by 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;
}
}
Any ideas how to avoid the duplication?
Upvotes: 2
Views: 982
Reputation: 140427
A non-answer here: there is no "code duplication" in your examples.
The point is: your abstract class drives a certain "layout" for your child class; but that is the essence of using an abstract class.
In other words: nothing to worry about here.
You are following well known, "approved" patterns; for example by nicely using the @Override annotation in your child class.
All fine, have a nice day!
Upvotes: 2
Reputation: 61969
There is hardly any code duplication in the code that I see here, but if you really want to "squeeze water from a stone", you can add a constructor to the base class, which accepts the input-filename and output-filename, and make each derived class pass its input-filename and output-filename to the constructor of the base class.
Upvotes: 4