Это хорошо, чтобы вставить зависимость доступа к базе данных в абстрактной фабрике? - PullRequest
0 голосов
/ 20 декабря 2011

У меня есть абстрактный фабричный класс StudentValidatorFactory, который, как предполагается, создает (на основе указанного параметра) различные экземпляры класса StudentValidator, в которые должна быть внедрена карта проверки (см. Код ниже).

public class StudentValidatorFactory{
    public static final int JUNIOR_STUDENT_TYPE = 1;

    public static final int SENIOR_STUDENT_TYPE = 2;

    public StudentValidator createStudentValidator(int studentType) throws StudentValidatorCreationException{
            Map<String,ValidationBean> validationMap = readValiationMapFromPersistentOrCachedStorage(studentType);
            switch (studentType){
                  case JUNIOR_STUDENT:
                      return new JuniorStudentValidator(validationMap);
                  case SENIOR_STUDENT:
                      return new SeniorStudentValidator(validationMap);
            }  
    }
}

public interface StudentValidator{
      void validate(Student student) throws StudentValidationException;
}


public class JuniorStudentValidator{
     private Map<String, ValidationBean> validationMap;           

     public JuniorStudentValidator(Map<String,ValidationBean> validationMap){
         this.validationMap = validationMap;
     }

     public void validate(Student student) throws StudentValidationException{
         // make use of validation map for apply junior student related validations on the student
     } 

}


public class SeniorStudentValidator{
     private Map<String, ValidationBean> validationMap;           

     public SeniorStudentValidator(Map<String,ValidationBean> validationMap){
         this.validationMap = validationMap;
     }


     public void validate(Student student) throws StudentValidationException{
         // make use of validation map for apply senior student related validations on the student
     } 

}

Мой вопрос касается StudentValidatorFactory.createStudentValidator (int studentType) метода, следует ли выполнять чтение карты проверки из постоянного хранилища (на основе типа студента) в методе create? Иначе говоря, должна ли фабрика знать / зависеть от таких деталей реализации?

Я был бы признателен, если бы существовало решение, позволяющее избежать оператора switch (studentType) при создании валидатора учащегося. Идея на моей голове - создать карту с внутренним управлением и выполнить конкретизацию конкретного класса StudentValidator с помощью отражения. .

Преимущества использования такого метода в том, что валидаторы гораздо проще тестировать (путем внедрения зависимостей).

1 Ответ

0 голосов
/ 20 декабря 2011

Извлеките readValiationMapFromPersistentOrCachedStorage(studentType) в отдельном интерфейсе службы StudentValidatorService и внедрите экземпляр службы в StudentValidatorFactory, используя аргумент свойства или конструктора:

public interface StudentValidatorService {
    Map<String,ValidationBean> getValidationMap(int studentType);
}

public class StudentValidatorFactory{
    public static final int JUNIOR_STUDENT_TYPE = 1;

    public static final int SENIOR_STUDENT_TYPE = 2;

    public StudentValidatorFactory(StudentValidatorService studentValidatorService) {
        this.studentValidatorService = studentValidatorService;
    }

    public StudentValidator createStudentValidator(int studentType) throws StudentValidatorCreationException{
            Map<String,ValidationBean> validationMap = studentValidatorService.getValidationMap(studentType);
            switch (studentType){
                  case JUNIOR_STUDENT:
                      return new JuniorStudentValidator(validationMap);
                  case SENIOR_STUDENT:
                      return new SeniorStudentValidator(validationMap);
            }  
    }
}

Теперь вы можете написать реализациюStudentValidatorService поддерживается базой данных.Или вы можете написать фиктивную реализацию для тестирования.Реализация теперь отделена от использования.


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

public enum StudentType {
    JUNIOR_STUDENT {
        public StudentValidator getValidator(Map<String,ValidationBean> validationMap) {
            return new JuniorStudentValidator(validationMap);
        }
    },
    SENIOR_STUDENT {
        public StudentValidator getValidator(Map<String,ValidationBean> validationMap) {
            return new SeniorStudentValidator(validationMap);
        }
    };

    public abstract StudentValidator getValidator(Map<String,ValidationBean> validationMap);
}

public class StudentValidatorFactory{

    public StudentValidatorFactory(StudentValidatorService studentValidatorService) {
        this.studentValidatorService = studentValidatorService;
    }

    public StudentValidator createStudentValidator(StudentType studentType) throws StudentValidatorCreationException{
            Map<String,ValidationBean> validationMap = studentValidatorService.getValidationMap(studentType);
            return studentType.getValidator(validationMap);
    }
}
...