Метод enum factory -style

В моем приложении может быть создано несколько различных отчетов (CSV, HTML и т.д.).

Вместо создания традиционного шаблона метода factory, я планировал добавить метод к телу констант перечисления, который создавал бы и возвращал соответствующий объект отчета.

public enum ReportType {
 CSV {
  @Override
  public Report create() {
   return new CSVReport();
  }
 },
 HTML {
  @Override
  public Report create() {
   return new HTMLReport();
  }
 };

 public abstract Report create();
}

С указанной константой перечисления ReportType я мог бы легко создать новый отчет, выполнив инструкцию вроде следующего:

ReportType.CSV.create()

Я хотел получить мнение других относительно использования этого подхода. Что ты думаешь об этом? Предпочитаете ли вы какой-либо другой подход, и если да, то почему?

Спасибо

Ответ 1

Я думаю, что оба подхода в порядке, но если вы не хотите знать, какой отчет вы генерируете, я считаю, что подход enum является лучшим. Например:

public class Person { 
    private String name;
    private ReportType myPreferedReportType;

    public ReportType getMyPreferedReportType(){
        return this.myPreferedReportType;
    }
    //other getters & setters...
}

предположите, что вы сохраняете экземпляр Person в базе данных и извлекаете его позже - если вы используете полиморфизм, вам не понадобится какой-либо коммутатор. Единственное, что вам нужно сделать, это для вызова метода create(). Как:

Person person = null; 
//... retrieve the person instance from database and generate a 
//report with his/her prefered report type...
Report report = person.getReportType.create();

Итак, если вы полагаетесь на полиморфизм, вам не нужно будет просить factory явно получить CVS/HTML/PDF, оставив эту работу самому Enum. Но, конечно, есть ситуации, когда вам может понадобиться использовать тот или иной, хотя я обычно использую подход enum регулярно.

Ответ 2

Какое преимущество вы получаете, используя перечисление, например, для создания отчета? Если бы у вас был factory -метод, вы бы создали экземпляр CSVReport (скажем), как показано ниже:

Report csvReport = ReportFactory.createCSVReport();

код > который, я думаю, передает намерение лучше, чем перечисление. Насколько я понимаю, перечисления представляют собой фиксированный набор констант, и использование его в качестве создания factory для экземпляра (хотя и работает) кажется мне неправильным использованием намерения Enumeration.

Ответ 3

Посмотрите Enum с шаблоном посетителя. С помощью этого подхода вы сможете динамически добавлять функциональность в перечисление без необходимости загрязнять само перечисление.

Ответ 4

Джошуа Блох (признанный эксперт по Java) на самом деле рекомендует этот подход в своей книге "Эффективная Java 2nd Edition" на стр. 17: Принудительное использование свойства singleton с приватным конструктор или тип перечисления.