美文网首页
设计模式那点事-万物皆可“建造者”(2)-利用lamda实现流式

设计模式那点事-万物皆可“建造者”(2)-利用lamda实现流式

作者: 小胖学编程 | 来源:发表于2021-10-28 21:58 被阅读0次

    是不是厌倦了大量if...else的代码,可以使用建造者模式来简化校验逻辑。

    1. 原理

    1.1 建造者模式

    回顾一下,建造者模式几个要素:

    1. 私有的构造方法;
    2. public的静态方法,用于创建Builder对象;
    3. 静态内部类Builder,内部的方法返回this对象;

    1.2 lamda表达式

    因为大量的校验逻辑需要传入到方法中:

    1. 需要借助与lamda的Function方法。
    2. 为了简化Function参数,可以使用Predicate+String来构造Function。

    1.3 友好异常和精确异常

    需要借助工具类:[JAVA基础篇23]—JAVA异常工具类ExceptionUtils的使用

    友好异常:实际用户看到的描述;
    精确异常:开发可以快速定位问题的描述(包含异常的代码位置)。

    2. 代码实现

    2.1 可以完成的细节

    1. 友好异常与精确异常;
    2. 快速失败与完全失败;
    3. 异常终止与捕获异常;

    2.2 定义Function的响应对象

    需要定义一个响应对象,作为Function的返回对象。需要包含如下的功能:

    @Getter
    public class ValidationError {
    
        /**
         * 错误信息,友好错误信息
         */
        private String friendlyErrorMsg;
    
        /**
         * 错误信息,精确的错误信息
         */
        private String accurateErrorMsg;
    
        /**
         * 实际异常的参数
         */
        private Object[] params;
    
        /**
         * 实际异常的属性名
         */
        private String field;
    
        /**
         * 错误码
         */
        private int errorCode;
    
        public ValidationError(String friendlyErrorMsg, Object[] params) {
            this.friendlyErrorMsg = friendlyErrorMsg;
            this.params = params;
        }
    
        public ValidationError(String friendlyErrorMsg, String accurateErrorMsg, Object[] params) {
            this.friendlyErrorMsg = friendlyErrorMsg;
            this.accurateErrorMsg = accurateErrorMsg;
            this.params = params;
        }
    
        public static ValidationError of(String friendlyErrorMsg, Object... params) {
            return new ValidationError(friendlyErrorMsg, params);
        }
    
        public static ValidationError of(String friendlyErrorMsg, String accurateErrorMsg, Object... params) {
            return new ValidationError(friendlyErrorMsg, accurateErrorMsg, params);
        }
    
    }
    

    2.3 定义异常父类

    用来在保存友好异常和精确异常:

    @Getter
    public class BaseException extends RuntimeException {
    
        /**
         * 错误信息,精确的错误信息
         */
        private String accurateErrorMsg;
    
        public BaseException(String accurateErrorMsg) {
            this.accurateErrorMsg = accurateErrorMsg;
        }
    
        public BaseException(String message, String accurateErrorMsg) {
            super(message);
            this.accurateErrorMsg = accurateErrorMsg;
        }
    
        public BaseException(String message, Throwable cause, String accurateErrorMsg) {
            super(message, cause);
            this.accurateErrorMsg = accurateErrorMsg;
        }
    
        public BaseException(Throwable cause, String accurateErrorMsg) {
            super(cause);
            this.accurateErrorMsg = accurateErrorMsg;
        }
    
        public BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace,
                String accurateErrorMsg) {
            super(message, cause, enableSuppression, writableStackTrace);
            this.accurateErrorMsg = accurateErrorMsg;
        }
    
    }
    

    2.4 建造者实现代码

    建造者要素

    /**
     * 建造者模式,来完成(对一个对象)链式校验逻辑。
     * 1. 私有的构造方法;
     * 2. public的静态方法,创建Builder对象
     * 3. 静态内部类 Builder完成主要逻辑;
     * 4. Builder里面提供的方法,返回this;
     * --------
     * 1. 为了规范数据的输出,参数可以要求传入Predicate和String 在代码内部构造Function对象
     *
     */
    public class FunctionalValidatorExample<T> {
    
        private FunctionalValidatorExample() {
        }
    
        public static <T> FunctionalValidatorExample.Builder<T> checkFrom(T element) {
            return new FunctionalValidatorExample.Builder<>(element);
        }
    
    
        public static class Builder<T> {
    
            /**
             * 待校验的对象
             */
            private T element;
    
            /**
             * 是否快速失败
             */
            private boolean failFast = true;
    
            private boolean catchException = false;
    
            /**
             * 校验逻辑对象
             */
            private List<Function<? super T, ValidationError>> validators = new LinkedList<>();
    
    
            Builder(T element) {
                this.element = element;
            }
    
            /**
             * 贪婪匹配后失败
             */
            public FunctionalValidatorExample.Builder<T> failOver() {
                failFast = false;
                return this;
            }
    
            /**
             * 是否捕获异常
             */
            public FunctionalValidatorExample.Builder<T> catchException() {
                catchException = true;
                return this;
            }
    
    
            /**
             * 校验逻辑
             *
             * @param validator 传入的方法逻辑,返回值规定了要返回ValidationError对象
             * @return this对象
             */
            public FunctionalValidatorExample.Builder<T> on(Function<? super T, ValidationError> validator) {
                validators.add(validator);
                return this;
            }
    
            /**
             * 校验逻辑,规定响应对象
             *
             * @param validatorPredicate 传入的校验逻辑
             * @param errorMsg 当出现异常时,希望的返回值
             * @return this对象
             */
            public FunctionalValidatorExample.Builder<T> on(Predicate<? super T> validatorPredicate, String errorMsg) {
                Objects.requireNonNull(errorMsg, "errorMsg is null");
                on(t -> validatorPredicate.test(t) ? null : ValidationError.of(errorMsg));
                return this;
            }
    
            /**
             * @param conditionPredicate 条件逻辑,条件为true时,才会执行validatorPredicate校验
             * @param validatorPredicate 校验逻辑,当返回true则输出null,当返回false则输出errorMsg
             * @param errorMsg 校验逻辑失败时返回值。
             */
            public FunctionalValidatorExample.Builder<T> onIf(Predicate<? super T> conditionPredicate,
                    Predicate<? super T> validatorPredicate, String errorMsg) {
                onIf(conditionPredicate, t -> validatorPredicate.test(t) ? null : ValidationError.of(errorMsg));
                return this;
            }
    
            /**
             * @param conditionPredicate 条件逻辑,条件为true时,才会执行function方法
             * @param validator 逻辑方法
             */
            public FunctionalValidatorExample.Builder<T> onIf(Predicate<? super T> conditionPredicate,
                    Function<? super T, ValidationError> validator) {
                validators.add(t -> conditionPredicate.test(t) ? validator.apply(t) : null);
                return this;
            }
    
            /**
             * 整合所有的异常描述
             */
            public ValidationResult check() {
                //返回对象
                ValidationResult result = ValidationResult.build();
                //校验逻辑
                for (Function<? super T, ValidationError> validator : validators) {
                    ValidationError validationError;
                    try {
                        validationError = validator.apply(element);
                    } catch (BaseException e) {
                        if (!catchException) {
                            throw e;
                        }
                        validationError = ValidationError.of(e.getMessage(), e.getAccurateErrorMsg());
                    } catch (Exception e) {
                        if (!catchException) {
                            throw e;
                        }
                        validationError = ValidationError.of("网络异常,请稍后再试", ExceptionUtil.getLogErrorMessage(e));
                    }
                    //加入到异常类中
                    result.addErrors(validationError);
                    //存在失败的
                    if (failFast && !result.isSuccess()) {
                        break;
                    }
                }
                return result;
            }
        }
    }
    

    存储异常的类:

    /**
     * 存储校验结果的类
     */
    @Getter
    public class ValidationResult {
    
        private List<ValidationError> sourceErrors = new LinkedList<>();
    
        private boolean success = true;
    
    
        private ValidationResult() {
        }
    
        public static ValidationResult build() {
            return new ValidationResult();
        }
    
        /**
         * 增加错误信息
         */
        public ValidationResult addErrors(ValidationError... errors) {
            if (errors != null && errors.length > 0) {
                sourceErrors.addAll(Arrays.asList(errors));
                success = false;
            }
            return this;
        }
    
        /**
         * 增加错误信息
         */
        public ValidationResult addErrors(Collection<ValidationError> errorList) {
            if (errorList != null && !errorList.isEmpty()) {
                sourceErrors.addAll(errorList);
                success = false;
            }
            return this;
        }
    }
    

    2.5 测试代码

    public class Test {
    
    
        public static void main(String[] args) {
            //待校验的对象
            User user = new User();
            user.setAge(12);
            user.setName("tom");
            //对象的校验
    
            ValidationResult validationResult = FunctionalValidatorExample.checkFrom(user)
                    .failOver()
                    .catchException()
                    .on(t -> t.getName().equals("libai"), "名字不符")
                    .onIf(t -> t.getGj().equals("china"), t -> t.getName().startsWith("王"), "不姓王")
                    .check();
            //获取错误源
            List<ValidationError> sourceErrors = validationResult.getSourceErrors();
            System.out.println(JSON.toJSONString(sourceErrors));
        }
    
    }
    

    系列文章

    设计模式那点事-万物皆可“建造者”

    相关文章

      网友评论

          本文标题:设计模式那点事-万物皆可“建造者”(2)-利用lamda实现流式

          本文链接:https://www.haomeiwen.com/subject/orkbaltx.html