Spring中接口的多个实现的管理

问题描述 投票:0回答:1

在我的 Spring 应用程序中,我有一些接口及其实现

public interface Validation(){
    boolean validate();
}

public interface ValidationLogicA extend Validation(){

}


public interface ValidationLogicB extend Validation() {

}

public interface ValidationLogicC extend Validation() {

}

public class ValidatorOne implementaion ValidationLogicA, ValidationLogicB {
    boolean validate(){
     // do logic
    };
}

public class ValidatorTwo implementaion ValidationLogicA, ValidationLogicC {
    boolean validate(){
     // do logic
    };
}

public class ValidatorThree implementaion ValidationLogicC {
    boolean validate(){
     // do logic
    };
}

所以上面代码的想法是:

  • 我可以注入一种类型的所有验证器(ValidationLogicA,ValidationLogicB,ValidationLogicC),并且验证器可以是公共的并且可以重用(例如ValidatorOne是ValidationLogicA和ValidationLogicB两者的逻辑)
  • 在调用者类中,只需注入验证的所有实现,例如:
@Component
public class CallerA {

    private final List<ValidationLogicA> validateOfA;
    
    public boolean doValidate(){
        // do something
    }
}

因此,通过上面的代码,将注入 ValidationLogicA 的所有实现(即 ValidatorOne 和 ValidatorTwo)来执行一些业务逻辑。 现在,如果我们有新的验证逻辑,例如 ValidationLogicD,其逻辑中也有 ValidatorOne,那么只需修改 ValidatorOne 并实现 ValidationLogicD 即可:

public class ValidatorOne implementaion ValidationLogicA, ValidationLogicB, ValidationLogicD

所以我的问题是,使用 spring bean,是否可以单独管理接口的所有实现(例如 ValidationLogicA),例如在不同的类配置中, 然后在该配置类中,我们只需添加或删除实现而不更改具体类(例如 ValidatorOne)

我正在尝试寻找另一个更好、更干净的解决方案

java spring design-patterns dependency-injection
1个回答
0
投票

您可以尝试使用此解决方案。要添加新的验证类型,您只需扩展枚举并实现验证:

public enum ValidationType {
    VALIDATION_A,
    VALIDATION_B,
    VALIDATION_C
}

public interface Validation {
    boolean validate();
    ValidationType getValidationType();
}

public abstract class ValidationLogicA implements Validation {
    public ValidationType getValidationType() {
        return ValidationType.VALIDATION_A;
    }
}

public interface Validator {
    boolean validate();
    Set<ValidationType> getValidationTypes();
}

@Service
public class ValidatorOne implements Validator {
    private static final Set<ValidationType> VALIDATION_TYPES = Set.of(ValidationType.VALIDATION_A, ValidationType.VALIDATION_B);

    @Autowired
    private List<Validation> validations;

    @Override
    public boolean validate() {
        for (Validation validation : getValidations()) {
            if (!validation.validate()) {
                return false;
            }
        }
        return true;
    }

    @Override
    public Set<ValidationType> getValidationTypes() {
        return VALIDATION_TYPES;
    }

    private List<Validation> getValidations() {
        return validations.stream()
                .filter(validation -> VALIDATION_TYPES.contains(validation.getValidationType()))
                .toList();
    }
}

@Service
public class CellarA {
    private Set<ValidationType> CELLAR_VALIDATION_TYPES = Set.of(ValidationType.VALIDATION_A, ValidationType.VALIDATION_B);

    @Autowired
    List<Validator> validators;

    public void doValidate() {
        for (Validator validator : getCellarValidators()) {
            // validate
        }
    }

    private List<Validator> getCellarValidators() {
        return validators.stream()
                .filter(validator -> validator.getValidationTypes().stream().anyMatch(CELLAR_VALIDATION_TYPES::contains))
                .toList();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.