Java интерфейс для entity/dto или передача метода по ссылке?

Я пытаюсь создать класс валидатор с несколькими простыми правилами проверки. Эти правила могут применяться одинаково к разным типам Hibernate entity (или DTO), и я хотел бы унифицировать этот класс без создания разных реализаций.

Я пытаюсь сделать это с помощью дженериков, но проблема в том, что, хотя каждый тип валидируемого объекта имеет определенный геттер (getCatalog), я не могу вызвать его с помощью дженериков не реализуя общий интерфейс или не расширяя абстрактный класс. Я думаю, что интерфейс для entity / dto в таком случае не является хорошим выбором, хотя может я и не прав и интерфейс типа Cataloged или HasCatalog допустим для таких целей..

Validator class
public class Validator<T> {

public boolean validate(List<T> objects, Function<T, Catalog> catalogGetter) {

    if (CollectionUtils.isEmpty(objects)) {
        return false;
    }
    if (differentCatalogsInLoadExist(objects, catalogGetter)) {
        return false;
    }
    if (catalogForObjectNotExists(objects, catalogGetter)) {
        return false;
    }
    return true;
}

private boolean differentCatalogsInLoadExist(List<T> objects, Function<T, Catalog> catalogGetter) {
    return objects.stream()
            .map(catalogGetter)
            .map(catalog -> catalog.getCatalogCode())
            .distinct()
            .count() > 1;
}

private boolean catalogForObjectNotExists(List<T> objects, Function<T, Catalog> catalogGetter) {
    return objects.stream()
            .map(catalogGetter)
            .findFirst()
            .isEmpty();
}

}


Основная моя цель - избавиться от этого Function<T, Catalog> catalogGetter

Может есть более красивый способ или вариант с интерфейсом тут допустим?
  • Вопрос задан
  • 331 просмотр
Пригласить эксперта
Ответы на вопрос 1
1. Я бы не стал делать в валидаторе сигнатуру, которая принимает список объектов.
Как минимум из-за того, что ему не нужен весь интерфейс, который даёт List. А как максимум - это просто не красиво.
2. Я бы не стал валидировать объекты, которые лежат в базе (считается, что раз объект попал в базу, то он уже валиден). Так что имеет смысл валидировать только DTO.
3. Вы правы, прокидывать лямбду для геттера в метод - это плохо.
я бы сделал билдер для валидатора, наподобие
// Псевдо-Java
var validator = new ValidatorBuilder<MyDto>()
                                .rule(d -> d.catalogues, catalogues -> catalogues.stream().map(c -> c.code).distinct().count() > 1)
                                // etc
                                .build();
var dto = //как-то получаем экземпляр dto
var dtoValid = validator.validate(dto);

PS:
Вдохновлялся шарповым FluentValidation - можете посмотреть на его API, но я бы не стал пытаться его портировать на Java, тк там много зависимостей от чисто шарповых штук
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы