规则执行器的设计实现

Posted dingwen_blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了规则执行器的设计实现相关的知识,希望对你有一定的参考价值。

规则执行器的设计实现

[!NOTE]

此规则执行器的设计旨在替代大量的ifelse ifelse嵌套,对代码进行优化。

其他规则以及实体,使用案例中使用的规则类参考完整代码。地址:https://gitee.com/dingwen-gitee/java8-study.git

1.使用场景

if (条件一){
  
}

if (条件二){
  
}

if (条件三){
  
}
...
  
  
if (){
  
}else if (){
  
}else {
  
}


if (条件1 && 条件2 || 条件3){
  
}

...

switch(条件){
    case: 条件1:
    break;
    ...
}

2.规则dto

package rule;

import java.util.List;
import java.util.Map;

/**
 * <p>
 * 规则Dto
 * 业务数据
 * </P>
 *
 * @author dingwen
 * @date 2021.09.09 09:52
 */
public class RuleDto<T> {
    /**
     * 规则Dto值
     */
    private T value;

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }
}

3.规则的抽象接口

  • 多条件返回Boolean类型
  • 多条件返回任意类型
  • 多条件无返回值(按照指定规则执行)
package rule;

/**
 * <p>
 * 规则的抽象接口
 * </P>
 *
 * @author dingwen
 * @date 2021.09.09 09:57
 */
public abstract class AbstractBaseRule<R, T> {

    /**
     * 执行
     *
     * @param ruleDto 规则dto
     * @return {@link Boolean}
     */
    Boolean executeBoolean(RuleDto<T> ruleDto) {
        return false;
    }

    /**
     * 执行
     *
     * @param ruleDto 规则dto
     * @return {@link R}
     */
    R executeObject(RuleDto<T> ruleDto) {
        return null;
    }

    /**
     * 执行
     * 没有返回值
     *
     * @param ruleDto 规则dto
     */
    void executeVoid(RuleDto<T> ruleDto){
    }
}

4.规则执行器

package rule;


import org.omg.CORBA.ORB;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 执行器构建规则服务
 * </P>
 *
 * @author dingwen
 * @date 2021.09.09 10:39
 */
public class RuleService<R, T> {
    /**
     * 规则对象集合
     */
    private final Map<Integer, List<AbstractBaseRule<R, T>>> ruleMap = new HashMap<>();

    /**
     * AND 规则列表
     */
    private final List<AbstractBaseRule<R, T>> ruleAndList = new ArrayList<>();
    /**
     * or 规则列表
     */
    private final List<AbstractBaseRule<R, T>> ruleOrList = new ArrayList<>();

    /**
     * 类型:
     * 1: AND
     * 0: OR
     */
    private int type = 1;

    /**
     * 和
     */
    private static final int AND = 1;
    /**
     * 或
     */
    private static final int OR = 0;

    private RuleService() {
    }

    public static <R, T> RuleService<R, T> getInstance() {
        return new RuleService<>();
    }


    /**
     * 和
     *
     * @return {@link RuleService<>}
     */
    public final RuleService<R, T> and() {
        type = AND;
        return this;
    }


    /**
     * 或
     *
     * @return {@link RuleService<>}
     */
    public final RuleService<R, T> or() {
        type = OR;
        return this;
    }

    /**
     * 构建器
     *
     * @param rule 规则
     * @return {@link RuleService<>}
     */
    public RuleService<R, T> builder(AbstractBaseRule<R, T> rule) {
        if (type == AND) {
            ruleAndList.add(rule);
        } else {
            ruleOrList.add(rule);
        }
        return this;
    }

    /**
     * 构建
     *
     * @return {@link RuleService<>}
     */
    public RuleService<R, T> build() {
        if (type == AND) {
            ruleMap.put(AND, ruleAndList);
        } else {
            ruleMap.put(OR, ruleOrList);
        }
        return this;
    }


    /**
     * 和
     *
     * @param ruleDto  规则dto
     * @param ruleList 规则列表
     * @return {@link Boolean}
     */
    private Boolean and(RuleDto<T> ruleDto, List<AbstractBaseRule<R, T>> ruleList) {
        return ruleList.stream().parallel().allMatch(rtAbstractBaseRule -> rtAbstractBaseRule.executeBoolean(ruleDto));
    }


    /**
     * 或
     *
     * @param ruleDto  规则dto
     * @param ruleList 规则列表
     * @return {@link Boolean}
     */
    private Boolean or(RuleDto<T> ruleDto, List<AbstractBaseRule<R, T>> ruleList) {
        return ruleList.stream().parallel().anyMatch(rtAbstractBaseRule -> rtAbstractBaseRule.executeBoolean(ruleDto));
    }


    /**
     * 执行
     *
     * @param ruleDto 规则dto
     * @return {@link Boolean}
     */
    public Boolean execute(RuleDto<T> ruleDto) {
        boolean result = false;
        if (ruleMap.containsKey(AND) && !ruleMap.containsKey(OR)) {
            result = and(ruleDto, ruleMap.get(AND));
        } else if (!ruleMap.containsKey(AND) && ruleMap.containsKey(OR)) {
            result = or(ruleDto, ruleMap.get(OR));
        } else if (ruleMap.containsKey(AND) && ruleMap.containsKey(OR)) {
            if (type == AND) {
                result = and(ruleDto, ruleMap.get(AND)) && or(ruleDto, ruleMap.get(AND));
            } else {
                result = and(ruleDto, ruleMap.get(OR)) || or(ruleDto, ruleMap.get(OR));
            }
        } else {
            return false;
        }
        ruleMap.clear();
        return result;
    }


    /**
     * 执行
     *
     * @param ruleDto 规则dto
     * @param rule    规则
     * @return {@link R}
     */
    public R execute(RuleDto<T> ruleDto, AbstractBaseRule<R, T> rule) {
        return rule.executeObject(ruleDto);
    }

    /**
     * 执行
     * 没有返回值
     *
     * @param ruleDto 规则dto
     * @param rule    规则
     */
    public void executeVoid(RuleDto<T> ruleDto, AbstractBaseRule<R, T> rule) {
        rule.executeVoid(ruleDto);
    }
}

5.使用

package rule;

import entity.Student;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  测试
 * </P>
 *
 * @author dingwen
 * @date 2021.09.09 12:01
 */
public class Test {
    public static void main(String[] args) {

        // 多值多判断情况
        RuleDto<Map<String, String>> usernameRuleDto = new RuleDto<>();

        HashMap<String, String> valueMap = new HashMap<>(2);
        valueMap.put(UserNameRule.class.getSimpleName(), "dingwen");
        valueMap.put(PasswordRule.class.getSimpleName(), "123456");
        usernameRuleDto.setValue(valueMap);

        RuleService<Boolean, Map<String, String>> ruleService = RuleService.getInstance();
//        Boolean r1 = ruleService.and()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .execute(usernameRuleDto);
//
//        System.out.println("r1 = " + r1);
//
//        Boolean r2 = ruleService.or()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .and()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .execute(usernameRuleDto);
//        System.out.println("r2 = " + r2);

//        Boolean r3 = ruleService.or()
//                .builder(new UserNameRule("din1gwen"))
//                .builder(new PasswordRule())
//                .build()
//                .or()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .execute(usernameRuleDto);
//        System.out.println("r3 = " + r3);

//        Boolean r4 = ruleService.and()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .and()
//                .builder(new UserNameRule("dingwen"))
//                .builder(new PasswordRule())
//                .build()
//                .execute(usernameRuleDto);
//        System.out.println("r4 = " + r4);


                Boolean r6 = ruleService.and()
                .builder(new UserNameRule("dingwen"))
                .builder(new PasswordRule())
                .build()
                .or()
                .builder(new UserNameRule("dingwen"))
                .builder(new PasswordRule())
                .build()
                .execute(usernameRuleDto);
        System.out.println("r6 = " + r6);


//        // 指定规则指定返回类型
//        RuleDto<Student> studentRuleDto = new RuleDto<>();
//        Student student = new Student();
//        student.setName("dingwen");
//        studentRuleDto.setValue(student);
//        Double sore = RuleService.<Double, Student>getInstance().execute(studentRuleDto, new StudentRule());
//        System.out.println("sore = " + sore);
//
//        // 指定规则没有返回值
//
//        RuleDto<String> stringRuleDto = new RuleDto<>();
//        stringRuleDto.setValue("y");
//
//        RuleService.<Object,String>getInstance().executeVoid(stringRuleDto,new PrintRule());
//
//
//        // 一个条件对应不同返回值
//        RuleDto<String> ruleDto = new RuleDto<>();
//        ruleDto.setValue("张三");
//        RuleService<Student, String> ruleService1 = RuleService.getInstance();
//        Student student1 = ruleService1.execute(ruleDto, new Student2Rule());
//        System.out.println("student1 = " + student1);


    }
}

以上是关于规则执行器的设计实现的主要内容,如果未能解决你的问题,请参考以下文章

作用域是什么?

是否可以动态编译和执行 C# 代码片段?

代码片段:Shell脚本实现重复执行和多进程

6大设计原则之开闭原则

选项卡执行android中下一个片段中存在的代码

十条实用的jQuery代码片段