美文网首页
设计模式那点事-万物皆可“建造者”(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实现流式

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

  • iOS开发:设计模式那点事

    iOS开发:设计模式那点事 iOS开发:设计模式那点事

  • Builder Pattern in Java

    建造者模式:建造者模式定义建造者模式应用场景实现案例Jdk中的建造者模式建造者模式的优点建造者模式的缺点 建造者模...

  • 静态内部类2

    利用静态内部类实现建造者模式,建造者模式是用静态内部类创建外部类对象,将整个建造过程和用户看到的界面分开来。 程序...

  • 建造者模式衍生的全局Dialog

    这篇小文将讲述我是如何根据建造者设计模式来实现一个全局Dialog。如果各位看官还不太了解建造者设计模式,建议可以...

  • 建造者模式(部件构造)

    目录 建造者模式的理念 从 POJO 到建造者模式的思考 怎么来实现建造者模式 建造者模式在Android源码中的...

  • 一些常见的设计模式总结

    1.工厂模式 Spring中的应用:BeanFactory 构造对象 2. 建造者设计模式 建设者设计模式是属于创...

  • 设计模式之建造者模式

    设计模式之建造者模式 Intro 简介 建造者模式: 建造者模式隐藏了复杂对象的创建过程,它把复杂对象的创建过程加...

  • 设计模式(2)-建造者模式

    引言 当遇到一个类中的参数非常多的时候,构造函数的定义会显得非常的冗长,可读性下降。并且这种时候,某些参数往往是可...

  • Retrofit

    Retrofit设计模式 动态代理,装饰模式,建造者模式,抽象工厂模式,适配器模式 建造者模式创建Retrofit...

网友评论

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

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