Я хочу реализовать универсальный валидатор для проверки бизнес-правил на моем уровне обслуживания с использованием Factory Design Pattern и добавлением некоторого рода цепочки правил, таких как Rules Engine.У меня есть рабочее решение, которое я не уверен, если это лучший способ сделать.
Вот мой вопрос: я хочу обеспечить безопасность типов во время компиляции, а не иметь / проверять типы классов во время выполнения.Таким образом, разработчик сможет безопасно использовать метод, не имея возможности ClassCastException.Вот последнее предупреждение, которое я хочу решить, но пока не смог сделать это, мне нужна помощь и открою для совета. Если что-то не понятно в моем дизайне:
Непроверенный вызов 'validate(T) 'как элемент типа raw' ... Validator '
Строки Я получаю предупреждение:
Validator validator = assignedSelectionValidatorFactory.createValidator(ValidationMode.SAVE);
validator.validate(new AssignedSelectionValidatable(assignSelectionRequestDto));
Вот мой интерфейс фабрики
public interface ValidatorFactory {
/**
* Creates factory which returns {@link Validator} based on the {@link ValidationMode}
*/
Validator createValidator(ValidationMode validationMode);
}
Вот моя конкретная реализация фабрики
@Component
public class AssignedSelectionValidatorFactory implements ValidatorFactory {
private AssignedSelectionSaveValidator assignedSelectionSaveValidator;
public AssignedSelectionValidatorFactory(AssignedSelectionSaveValidator assignedSelectionSaveValidator) {
this.assignedSelectionSaveValidator = assignedSelectionSaveValidator;
}
@Override
public Validator createValidator(ValidationMode validationMode) {
switch (validationMode) {
case SAVE:
return assignedSelectionSaveValidator;
default:
return null;
}
}
}
Вот интерфейс Validator
public interface Validator<T extends Validatable> {
/**
* Validates each validation rules
*/
void validate(T objectsToValidate);
}
Вот конкретная реализация интерфейса Validator.Это вызывает правила проверки в его реализации
@Component
public class AssignedSelectionSaveValidator implements Validator<AssignedSelectionValidatable> {
private AssignedSelectionUniqueRule assignedSelectionUniqueRule;
AssignedSelectionSaveValidator(AssignedSelectionUniqueRule assignedSelectionUniqueRule) {
this.assignedSelectionUniqueRule = assignedSelectionUniqueRule;
}
@Override
public void validate(AssignedSelectionValidatable assignedSelectionValidatable) {
assignedSelectionUniqueRule.apply(assignedSelectionValidatable.getAssignSelectionRequestDto());
}
}
А вот и правило проверки.Каждое правило проверки является независимым, поэтому его можно использовать повторно.Также я не мог заставить их реализовать некоторый интерфейс ValidationRule -> apply (T genericInterface), поскольку каждый ValidationRule может получать разные параметры.И я не хочу делать его более сложным, получая параметры из интерфейса, но также открыты для любых предложений.
@Component
public class AssignedSelectionUniqueRule {
private AssignedSelectionRepository assignedSelectionRepository;
public AssignedSelectionUniqueRule(AssignedSelectionRepository assignedSelectionRepository) {
this.assignedSelectionRepository = assignedSelectionRepository;
}
public void apply(AssignSelectionRequestDto objectToValidate) {
Optional<AssignedSelection> foundAssignedSelection =
assignedSelectionRepository.getBy(objectToValidate.getSelectionDto().getId(),
objectToValidate.getCampaignUuid());
if (foundAssignedSelection.isPresent()) {
throw new BadRequestException(
"AssignedSelection is already exists with campaignUuid: {} and selectionUuid: {}");
}
}
}