在抽象工厂中插入数据库访问依赖项是否合适?

时间:2011-12-20 12:32:36

标签: java dependency-injection abstract-factory

我有一个抽象工厂类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方法中从持久存储中读取验证图(基于学生类型)?否则说,工厂应该知道/依赖这些实施细节吗?

我很欣赏在创建学生验证器时是否会有一个避免切换(studentType)语句的解决方案 - 我的想法是拥有一个内部管理的地图并通过反射执行StudentValidator具体类实例化

使用这种技术的好处是验证器更容易被测试(通过依赖注入)。

1 个答案:

答案 0 :(得分:0)

在分离的服务接口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);
    }
}