Использование Заводской метод шаблон:
public enum ReportType {EXCEL, CSV};
@Service
public class ReportFactory {
@Resource
private ExcelReport excelReport;
@Resource
private CSVReport csvReport
public Report forType(ReportType type) {
switch(type) {
case EXCEL: return excelReport;
case CSV: return csvReport;
default:
throw new IllegalArgumentException(type);
}
}
}
Тип отчета enum
может быть создан Spring при вызове контроллера с ?type=CSV
:
class MyController{
@Resource
private ReportFactory reportFactory;
public HttpResponse getReport(@RequestParam("type") ReportType type){
reportFactory.forType(type);
}
}
Однако ReportFactory
довольно неуклюжий и требует модификации каждый раз, когда вы добавляете новый тип отчета. Если список типов отчетов исправлен, это нормально. Но если вы планируете добавлять все больше и больше типов, это более надежная реализация:
public interface Report {
void generateFile();
boolean supports(ReportType type);
}
public class ExcelReport extends Report {
publiv boolean support(ReportType type) {
return type == ReportType.EXCEL;
}
//...
}
@Service
public class ReportFactory {
@Resource
private List<Report> reports;
public Report forType(ReportType type) {
for(Report report: reports) {
if(report.supports(type)) {
return report;
}
}
throw new IllegalArgumentException("Unsupported type: " + type);
}
}
В этой реализации добавить новый тип отчета так же просто, как добавить новый компонент, реализующий Report
и новое значение перечисления ReportType
. Вы можете обойтись без enum
и использования строк (возможно, даже имен бинов), однако я считаю, что печатать очень полезно.
Последняя мысль: Report
имя немного неудачно. Класс Report
представляет (без сохранения состояния?) Инкапсуляцию некоторой логики (шаблон Стратегия ), тогда как название предполагает, что он инкапсулирует значение (данные). Я бы предложил ReportGenerator
или такой.