设计模式-责任链模式

1. 责任链- 使用校验的责任链 完成校验逻辑

责任链模式 其核心在将逻辑抽象成一条链条 (可维护的)核心思想是 每个节点都能干预主流程的执行 建立统一的上下文管理不同字段的校验链 主流程 能汇聚每个节点的结果。

1.1 首先定义好注解,并在实体类中添加注解
java 复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Length {

    int value();
}
java 复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Max {

    int value();
}
java 复制代码
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Min {

    int value();
}
java 复制代码
public class User {
    public String getName() {
        return name;
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Length(5)
    private String name;

    @Max(15)
    @Min(17)
    private Integer age;
}

设计出整个校验链,使用 hanlders 做为校验处理器的List

java 复制代码
    private final List<ValidatorHandler> handlers = new ArrayList<>();

封装出 addHandler的方法 用来向外暴露添加校验处理器,并以顺序作为优先级

java 复制代码
   public void addLastHandler(ValidatorHandler handler) {
        this.handlers.add(handler);
    }
1.2 首先抽象出校验的类和方法

在 validate 方法中添加校验的对象,通过反射的方式对字段中需要做的校验抽象出来 ,并构建出校验的链条

java 复制代码
public class Validator {

   public  void validate(Object bean) throws ValidatorException, IllegalAccessException {
         // 责任链模式
        Class<?> aClass = bean.getClass();

        for (Field declaredField : aClass.getDeclaredFields()) {
            // 私有属性添加
            declaredField.setAccessible(true);
            buildValidateChain(declaredField).validate(declaredField.get(bean));
        }

    }

    private ValidatorChain buildValidateChain(Field declaredField) {
        ValidatorChain chain = new ValidatorChain();

        Max max = declaredField.getAnnotation(Max.class);
        if ( max != null) {
            chain.addLastHandler(new MaxValidatorHandler(max.value()));
        }
        Min min = declaredField.getAnnotation(Min.class);
        if (min != null) {
            chain.addLastHandler( new MinValidatorHandler(min.value()));
        }
        Length length = declaredField.getAnnotation(Length.class);
        if (length != null) {
            chain.addLastHandler(new LengthValidatorHandler(length.value()));
        }

        return chain;
    }
}
1.3 ValidatorHandler 作为校验处理器 对各种校验逻辑的封装
java 复制代码
public interface ValidatorHandler {

    void validate(Object bean,ValidatorContext context) ;
}


//  各种不同的校验器实现 
public class MaxValidatorHandler implements ValidatorHandler {
    //
    private final Integer max;

    public MaxValidatorHandler (Integer max ) {
        this.max = max;
    }


    // 校验器的告警机制停止校验 每个校验器都可以通过上下文对流程进行干预
    @Override
    public void validate(Object bean, ValidatorContext context) {
        
        if(bean instanceof Integer) {
            if(max < (Integer) bean) {
                context.appendError("Max number is greater than " + max); 
        } 

    }

}

// 最小值的校验
public class MinValidatorHandler implements ValidatorHandler {

    private final Integer min;

    public MinValidatorHandler (Integer min ) {
       this.min = min;
    }

    @Override
    public void validate(Object bean,  ValidatorContext context) {

        if(bean instanceof Integer) {
            if(min > (Integer) bean) {
                context.appendError("Max number is min than " + min);
            }
        }

    }
}


// 长度的校验
public class LengthValidatorHandler implements ValidatorHandler {

    private final Integer length;

    public LengthValidatorHandler(Integer length ) {
       this.length = length;
    }

    @Override
    public void validate(Object bean,ValidatorContext context) throws ValidatorException {

        if(bean instanceof String) {
            if(length < ((String) bean).length()) {
                    context.appendError("Max length is greater than " + length);
            }
        }

    }
}
1.4 在具体的校验方法中的处理

在 validatorContext对象中封装一些公用的方法(如当前校验到的节点的下表,当前错误的信息的List的封装)和当前校验节点的下标。使用 ValidatorHandler的实现各种校验逻辑的封装,进行校验。

java 复制代码
    // 组装链条
    public void validate(Object object) throws ValidatorException {

//      for (ValidatorHandler handler : handlers) {
//               handler.validate(object,context);
//               if(context.shouldStopChain()){
//                   break;
//               }
//        }
         ValidatorContext context = new ValidatorContext(object);
        while(true) {
            Integer currentIndex = context.getCurrentIndex();
            if(currentIndex == handlers.size() ) {
                break;
            }
            ValidatorHandler validatorHandler = handlers.get(currentIndex);
            validatorHandler.validate(context.getValue(),context);
            // 没有调用 doNext函数的情况
            if(currentIndex.equals(context.getCurrentIndex())){
               break;
            }
        }

        context.throwExceptionIfNecessary();
    }
相关推荐
金銀銅鐵3 小时前
带您看懂字节码指令(一):一帧里有什么
java·后端·ai编程
nice_lcj5205 小时前
【从零理解 Spring AI · 14】RAG 的四个环节:加载、切分、向量化、检索
java·spring boot·embedding·向量数据库·rag·spring ai·ai应用开发
学长毕设6 小时前
基于springboot科创竞赛信息平台-附源码
java·spring boot·后端
聪明的笨猪猪7 小时前
Java 工程案例:AI 生成 @Async 异步线程池踩坑
java·经验分享·面试·ai编程
学长毕设7 小时前
基于SpringBoot公务员考试交流平台-附源码
java·spring boot·后端
SL_staff9 小时前
私有化低代码:面向强监管行业的可控数字化实践
java·低代码
三翼鸟数字化技术团队10 小时前
高性能存储引擎RocksDB:原理与Java生态实践
java
SL_staff10 小时前
JVS-APS有限产能建模的七个刚性支点:面向产线真实约束的技术实现解析
java·开源·全栈
特立独行的猫A10 小时前
少 3 个环节、少 1 次 ABI、少 3500 行代码:cj-tauri 与 Ionic/Capacitor 的鸿蒙桥接机制对比
java·后端·python
学长毕设11 小时前
基于SpringBoot的高校后勤报修管理系统-附源码
java·spring boot·后端