Создать абстрактную сущность для внешней библиотеки с реализацией в микросервисах (в микросервисах @Entity)

Подскажите, пожалуйста. Создаю внешнюю библиотеку в которой есть абстрактная фабрика

public abstract class GenerateFactory {

    protected Map<Class<?>, Generate> generateMap = new HashMap<>();

    public void register(Class<?> inputReportData, Generate generate) {
        generateMap.put(inputReportData, generate);
    }

    public Generate createInstance(Class<? extends Object> inputReportData) {

        return Optional.ofNullable(generateMap.get(inputReportData)).orElseThrow(NotSupportedGenerateException::new);
    }
}

Данная фабрика создает в зависимости от переданного объекта Generate реализацию создания документа. В разных микросервисах требования к созданию документа разные. А inputReportData (намеренно здесь написал Class<?>, чтобы подчеркнуть, что она должна быть абстрактной) в данный момент эта сущность представляет собой Enum, но общий Enum делать - не гуд, так как инкапсуляция нарушается).

public interface Generate<T> {

InputDataSetEnum getInputDataSet();

ReportPrintData convertToReportData(T dataSource);

@Autowired
default void registryGenerate(GenerateFactory factory) {
    factory.register(getInputDataSet(), this);
}

}

В каждом микросервисе есть сущность ReportDataSetEntity

@Entity
@Table(name = "report_data_set")
public class ReportDataSetEntity {
   @Id
   @Column(name = "id", nullable = false)
   private Long id;

   @Column(name = "template_id", nullable = false, unique = true)
   private String templateId;

   @Column(name = "input_data_set")
   @Enumerated(value = EnumType.STRING)
   private InputDataSetEnum inputDataSetEnum;

   //getter and setter
}

дак вот вопрос какой абстракцией описать ключ в protected Map<Class<?>, Generate> generateMap = new HashMap<>() ? Или реализовывать свой Maр ?!


Ответы (1 шт):

Автор решения: Roman-Stop RU aggression in UA

Тут я предполагаю, что ключ в фабрике (inputReportData) - это тип отчета, и поле inputDataSetEnum уникально в таблице ReportDataSetEntity.

В библиотеке создайте понятия тип отчета, выраженное интерфейсом ReportType:

interface ReportType {
};

public abstract class GenerateFactory {

  protected Map<ReportType, Generate> generateMap = new HashMap<>();

...}

В сервисах реализуйте этот интерфейс в enum:

public enum InputDataSetEnum implements ReportType {
...
}

Теперь без проблем можно регистрировать разные типы отчетов в фабрике, и нет глобального перечисления типа отчетов и библиотека о них не знает. О типах отчетов как и раньше знает только сервис.

Единственное что изменили, это то, что типы отчетов сервиса сделали типами отчетов, которые понимает фабрика (на своем абстрактом уровне, т.е. она умеет их только сравнивать).

→ Ссылка