# 规则决策树
# 1、需求
一棵树上有4颗果实,张三根据条件获取到果实B,其中判断条件为,摘果实的必须为男并且年龄必须大于25
# 2、屎山
# 2.1 错误案例
public class EngineController {
private Logger logger = LoggerFactory.getLogger(EngineController.class);
public String process(final String userId, final String userSex, final int userAge) {
logger.info("ifelse实现方式判断用户结果。userId:{} userSex:{} userAge:{}", userId, userSex, userAge);
if ("man".equals(userSex)) {
if (userAge < 25) {
return "果实A";
}
if (userAge >= 25) {
return "果实B";
}
}
if ("woman".equals(userSex)) {
if (userAge < 25) {
return "果实C";
}
if (userAge >= 25) {
return "果实D";
}
}
return null;
}
}
测试:
@Test
public void test_EngineController() {
EngineController engineController = new EngineController();
String process = engineController.process("Oli09pLkdjh", "man", 29);
logger.info("测试结果:{}", process);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 2.2 分析
由于屎山中大量的if..else堆叠,代码不易扩展性,后期如果添加新的需求,比如要求身高为175以上,则需要在原有代码上更改,违背开闭原则
# 3、组合模式实现规则决策树
为了解决屎山带来的代码扩展性低,耦合度高的问题,使用组合模式实现决策引擎,并动态配置树节点的子叶与果实,实现动态过滤
# 3.1 树的定义
树包含树根节点,树节点信息,树线信息(使节点与节点之间相互连接)
# 3.1.1 树根节点定义
package top.tec.domain.model.vo;
import lombok.Data;
/**
* @author: hujincheng
* @description: TreeRoot 树根信息
* @create: 2024-06-26 23:28
*/
@Data
public class TreeRoot {
/**
* 规则树ID
*/
private Long treeId;
/**
* 树根节点ID
*/
private Long treeRootNodeId;
/**
* 规则树名称
*/
private String treeName;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 3.1.2 树节点定义
package top.tec.domain.model.vo;
import lombok.Data;
import java.util.List;
/**
* @author: hujincheng
* @description: TreeNode 规则树节点信息
* @create: 2024-06-26 23:30
*/
@Data
public class TreeNode {
/**
* 规则树ID
*/
private Long treeId;
/**
* 规则树节点ID
*/
private Long treeNodeId;
/**
* 节点类型 [ 叶子: 1 , 果实: 2 ]
*/
private Integer nodeType;
/**
* 节点值(果实) [只需要存储果实的值即可:nodeType=2]
*/
private String nodeValue;
/**
* 规则Key(对应的过滤器名称)
*/
private String ruleKey;
/**
* 规则描述
*/
private String ruleDesc;
/**
* 节点链路
*/
private List<TreeNodeLink> treeNodeLinkList;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# 3.1.3树线信息定义
package top.tec.domain.model.vo;
import lombok.Data;
/**
* @author: hujincheng
* @description: TreeNodeLink 规则树线信息
* @create: 2024-06-27 00:02
*/
@Data
public class TreeNodeLink {
/**
* 节点From
*/
private Long nodeIdFrom;
/**
* 节点To
*/
private Long nodeIdTo;
/**
* 限定类型;
* 1:=;
* 2:>;
* 3:<;
* 4:>=;
* 5<=;
* 6:enum[枚举范围]
*/
private Integer ruleLimitType;
/**
* 限定值
*/
private String ruleLimitValue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 3.1.4 规则树聚合定义
package top.tec.domain.model.aggregates;
import lombok.Builder;
import lombok.Data;
import top.tec.domain.model.vo.TreeNode;
import top.tec.domain.model.vo.TreeRoot;
import java.util.Map;
/**
* @author: hujincheng
* @description: TreeRich 规则树聚合
* @create: 2024-06-27 00:06
*/
@Data
@Builder
public class TreeRich {
/**
* 树根信息
*/
private TreeRoot treeRoot;
/**
* (所有节点)树节点ID -> 子节点
*/
private Map<Long, TreeNode> treeNodeMap;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 3.1.5 解释
树根节点代表整颗树的首节点位置,类似二叉树,在每个节点下通过树线连接

# 3.2 规则引擎的定义
# 3.2.1 为什么要定义规则引擎
为了外部调用规则树实现规则的决策
测试时代码:
//定义规则树引擎
IEngine treeEngineHandle = new TreeEngineHandle();
//执行规则引擎决策
EngineResult result = treeEngineHandle.process(10001L, "Oli09pLkdjh", treeRich, decisionMatter);
1
2
3
4
5
2
3
4
5
# 3.2.2 定义引擎统一返回
package top.tec.domain.model.vo;
import lombok.Builder;
import lombok.Data;
/**
* @author: hujincheng
* @description: EngineResult 决策结果
* @create: 2024-06-27 00:10
*/
@Data
@Builder
public class EngineResult {
/**
* 执行结果
*/
private boolean isSuccess;
/**
* 用户ID
*/
private String userId;
/**
* 规则树ID
*/
private Long treeId;
/**
* 果实节点ID
*/
private Long nodeId;
/**
* 果实节点值
*/
private String nodeValue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 3.2.2 定义规则引擎接口
package top.tec.domain.service.engine;
import top.tec.domain.model.aggregates.TreeRich;
import top.tec.domain.model.vo.EngineResult;
import java.util.Map;
/**
* @author: hujincheng
* @description: IEngine 规则树引擎
* @create: 2024-06-27 00:08
*/
public interface IEngine {
/**
* 处理引擎
*/
EngineResult process(Long treeId, String userId, TreeRich treeRich, Map<String,String> decisionMatter);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 3.2.3 定义引擎配置
由于当前环境为maven环境非String容易中,故配置静态代码块加载条件过滤器
package top.tec.domain.service.engine;
import top.tec.domain.service.logic.LogicFilter;
import top.tec.domain.service.logic.impl.SGFilter;
import top.tec.domain.service.logic.impl.UserAgeFilter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author: hujincheng
* @description: EngineConfig 加载配置过滤器
* @create: 2024-06-27 00:17
*/
public class EngineConfig {
protected static Map<String, LogicFilter> filterMap = new ConcurrentHashMap<>();
static {
filterMap.put("SGFilter", new SGFilter());
filterMap.put("userAge", new UserAgeFilter());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 3.2.4 定义规则引擎抽象实现(实现统一决策)
根据定义的线规则决策器决策是否满足条件,从而获取到满足条件的决策结果
package top.tec.domain.service.engine;
import top.tec.domain.model.aggregates.TreeRich;
import top.tec.domain.model.vo.EngineResult;
import top.tec.domain.model.vo.TreeNode;
import top.tec.domain.model.vo.TreeRoot;
import top.tec.domain.service.logic.LogicFilter;
import java.util.Map;
/**
* @author: hujincheng
* @description: EngineBase
* @create: 2024-06-27 00:16
*/
public abstract class EngineBase extends EngineConfig implements IEngine {
@Override
public abstract EngineResult process(Long treeId, String userId, TreeRich treeRich, Map<String, String> decisionMatter);
protected TreeNode engineDecisionMaker(TreeRich treeRich, Map<String, String> decisionMatter) {
TreeRoot treeRoot = treeRich.getTreeRoot();
//获取决策树根节点ID
Long rootNodeId = treeRoot.getTreeRootNodeId();
//获取决策树节点列表
Map<Long, TreeNode> treeNodeMap = treeRich.getTreeNodeMap();
TreeNode treeNodeInfo = treeNodeMap.get(rootNodeId);
//判断是否是叶子节点
while (null != treeNodeInfo && treeNodeInfo.getNodeType().equals(1)) {
String ruleKey = treeNodeInfo.getRuleKey();
//获取线规则决策器
LogicFilter logicFilter = filterMap.get(ruleKey);
if (null == logicFilter) {
throw new RuntimeException("规则ruleKey:" + ruleKey + "对应的过滤器未定义");
}
String matterValue = logicFilter.matterValue(decisionMatter);
Long nextNodeId = logicFilter.filter(matterValue, treeNodeInfo.getTreeNodeLinkList());
treeNodeInfo = treeNodeMap.get(nextNodeId);
System.out.println("决策树引擎=>" + treeRoot.getTreeName() + "treeNode:" + treeNodeInfo.getTreeNodeId() + " ruleKey:" + ruleKey + " matterValue:" + matterValue);
}
return treeNodeInfo;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 3.2.5 定义规则引擎默认具体实现
具体实现中目前仅处理决策结果返回
package top.tec.domain.service.engine.impl;
import top.tec.domain.model.aggregates.TreeRich;
import top.tec.domain.model.vo.EngineResult;
import top.tec.domain.model.vo.TreeNode;
import top.tec.domain.service.engine.EngineBase;
import java.util.Map;
/**
* @author: hujincheng
* @description: TreeEngineHandle 决策树引擎实现
* @create: 2024-06-27 00:18
*/
public class TreeEngineHandle extends EngineBase {
@Override
public EngineResult process(Long treeId, String userId, TreeRich treeRich, Map<String, String> decisionMatter) {
//处理决策
TreeNode treeRoot = engineDecisionMaker(treeRich,decisionMatter);
//返回决策结果
return EngineResult.builder()
.isSuccess(Boolean.TRUE)
.userId(userId)
.treeId(treeId)
.nodeId(treeRoot.getTreeNodeId())
.nodeValue(treeRoot.getNodeValue())
.build();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3.3 线规则决策过滤器
相信引擎定义完成之后,会存在引擎配置中的线规则决策过滤器的疑问,接下来,他来了
# 3.3.1 定义统一线规则过滤器核心接口
方便扩展其他规则过滤器
package top.tec.domain.service.logic;
import top.tec.domain.model.vo.TreeNodeLink;
import java.util.List;
import java.util.Map;
/**
* @author: hujincheng
* @description: LogicFilter 过滤器
* @create: 2024-06-27 00:31
*/
public interface LogicFilter {
/**
* 逻辑决策器
*
* @param matterValue 决策值
* @param treeNodeLineInfoList 决策的线节点
* @return 下一个节点Id
*/
Long filter(String matterValue, List<TreeNodeLink> treeNodeLineInfoList);
/**
* 获取决策值
*
* @param decisionMatter 决策物料
* @return 决策值
*/
String matterValue(Map<String, String> decisionMatter);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 3.3.2 定义线规则过滤器抽象实现
规则过滤器中核心过滤规则在抽象抽象实现中实现,是为了扩展其他过滤器时不需要过多关注决断过滤过程,扩展时仅需提供需要决断的字段即可
package top.tec.domain.service.logic;
import top.tec.domain.model.vo.TreeNodeLink;
import java.util.List;
import java.util.Map;
/**
* @author: hujincheng
* @description: BaseLogic 过滤逻辑实现
* @create: 2024-06-27 00:36
*/
public abstract class BaseLogic implements LogicFilter {
@Override
public Long filter(String matterValue, List<TreeNodeLink> treeNodeLinkList) {
//根据线信息节点决断,返回下个节点Id
for (TreeNodeLink nodeLine : treeNodeLinkList) {
if (decisionLogic(matterValue, nodeLine)) {
return nodeLine.getNodeIdTo();
}
}
throw new RuntimeException("所有线都不匹配当前matterValue: " + matterValue);
//return 0L;
}
/**
* 具体决断
*/
private boolean decisionLogic(String matterValue, TreeNodeLink nodeLink) {
switch (nodeLink.getRuleLimitType()) {
case 1:
return matterValue.equals(nodeLink.getRuleLimitValue());
case 2:
return Double.parseDouble(matterValue) > Double.parseDouble(nodeLink.getRuleLimitValue());
case 3:
return Double.parseDouble(matterValue) < Double.parseDouble(nodeLink.getRuleLimitValue());
case 4:
return Double.parseDouble(matterValue) <= Double.parseDouble(nodeLink.getRuleLimitValue());
case 5:
return Double.parseDouble(matterValue) >= Double.parseDouble(nodeLink.getRuleLimitValue());
default:
return false;
}
}
@Override
public abstract String matterValue(Map<String, String> decisionMatter);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 3.3.3 定义具体过滤节点实现规则
# 3.3.3.1 性别过滤
package top.tec.domain.service.logic.impl;
import top.tec.domain.service.logic.BaseLogic;
import java.util.Map;
public class UserGenderFilter extends BaseLogic {
@Override
public String matterValue(Map<String, String> decisionMatter) {
return decisionMatter.get("gender");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.3.3.2 年龄过滤
package top.tec.domain.service.logic.impl;
import top.tec.domain.service.logic.BaseLogic;
import java.util.Map;
public class UserAgeFilter extends BaseLogic {
@Override
public String matterValue(Map<String, String> decisionMatter) {
return decisionMatter.get("age");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.3.3.3 身高过滤
package top.tec.domain.service.logic.impl;
import top.tec.domain.service.logic.BaseLogic;
import java.util.Map;
/**
* @author: hujincheng
* @description: SGFilter 身高
* @create: 2024-06-26 23:17
*/
public class SGFilter extends BaseLogic {
@Override
public String matterValue(Map<String, String> decisionMatter) {
return decisionMatter.get("sg");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3.4 测试
# 3.4.1 定义决策树,以及相关线决策器上使用的相关规则,以及叶子节点与果实节点
private TreeRich treeRich;
@Before
public void init() {
// 节点:1
TreeNode treeNode_01 = new TreeNode();
treeNode_01.setTreeId(10001L);
treeNode_01.setTreeNodeId(1L);
treeNode_01.setNodeType(1);
treeNode_01.setNodeValue(null);
treeNode_01.setRuleKey("SGFilter");
treeNode_01.setRuleDesc("身高");
// 链接:1->11
TreeNodeLink treeNodeLink_11 = new TreeNodeLink();
treeNodeLink_11.setNodeIdFrom(1L);
treeNodeLink_11.setNodeIdTo(11L);
treeNodeLink_11.setRuleLimitType(3);
treeNodeLink_11.setRuleLimitValue("175");
// 链接:1->12
TreeNodeLink treeNodeLink_12 = new TreeNodeLink();
treeNodeLink_12.setNodeIdFrom(1L);
treeNodeLink_12.setNodeIdTo(12L);
treeNodeLink_12.setRuleLimitType(5);
treeNodeLink_12.setRuleLimitValue("175");
List<TreeNodeLink> treeNodeLinkList_1 = new ArrayList<>();
treeNodeLinkList_1.add(treeNodeLink_11);
treeNodeLinkList_1.add(treeNodeLink_12);
treeNode_01.setTreeNodeLinkList(treeNodeLinkList_1);
// 节点:11
TreeNode treeNode_11 = new TreeNode();
treeNode_11.setTreeId(10001L);
treeNode_11.setTreeNodeId(11L);
treeNode_11.setNodeType(1);
treeNode_11.setNodeValue(null);
treeNode_11.setRuleKey("userAge");
treeNode_11.setRuleDesc("用户年龄");
// 链接:11->111
TreeNodeLink treeNodeLink_111 = new TreeNodeLink();
treeNodeLink_111.setNodeIdFrom(11L);
treeNodeLink_111.setNodeIdTo(111L);
treeNodeLink_111.setRuleLimitType(3);
treeNodeLink_111.setRuleLimitValue("25");
// 链接:11->112
TreeNodeLink treeNodeLink_112 = new TreeNodeLink();
treeNodeLink_112.setNodeIdFrom(11L);
treeNodeLink_112.setNodeIdTo(112L);
treeNodeLink_112.setRuleLimitType(5);
treeNodeLink_112.setRuleLimitValue("25");
List<TreeNodeLink> treeNodeLinkList_11 = new ArrayList<>();
treeNodeLinkList_11.add(treeNodeLink_111);
treeNodeLinkList_11.add(treeNodeLink_112);
treeNode_11.setTreeNodeLinkList(treeNodeLinkList_11);
// 节点:12
TreeNode treeNode_12 = new TreeNode();
treeNode_12.setTreeId(10001L);
treeNode_12.setTreeNodeId(12L);
treeNode_12.setNodeType(1);
treeNode_12.setNodeValue(null);
treeNode_12.setRuleKey("userAge");
treeNode_12.setRuleDesc("用户年龄");
// 链接:12->121
TreeNodeLink treeNodeLink_121 = new TreeNodeLink();
treeNodeLink_121.setNodeIdFrom(12L);
treeNodeLink_121.setNodeIdTo(121L);
treeNodeLink_121.setRuleLimitType(3);
treeNodeLink_121.setRuleLimitValue("25");
// 链接:12->122
TreeNodeLink treeNodeLink_122 = new TreeNodeLink();
treeNodeLink_122.setNodeIdFrom(12L);
treeNodeLink_122.setNodeIdTo(122L);
treeNodeLink_122.setRuleLimitType(5);
treeNodeLink_122.setRuleLimitValue("25");
List<TreeNodeLink> treeNodeLinkList_12 = new ArrayList<>();
treeNodeLinkList_12.add(treeNodeLink_121);
treeNodeLinkList_12.add(treeNodeLink_122);
treeNode_12.setTreeNodeLinkList(treeNodeLinkList_12);
// 节点:111
TreeNode treeNode_111 = new TreeNode();
treeNode_111.setTreeId(10001L);
treeNode_111.setTreeNodeId(111L);
treeNode_111.setNodeType(2);
treeNode_111.setNodeValue("果实A");
// 节点:112
TreeNode treeNode_112 = new TreeNode();
treeNode_112.setTreeId(10001L);
treeNode_112.setTreeNodeId(112L);
treeNode_112.setNodeType(2);
treeNode_112.setNodeValue("果实B");
// 节点:121
TreeNode treeNode_121 = new TreeNode();
treeNode_121.setTreeId(10001L);
treeNode_121.setTreeNodeId(121L);
treeNode_121.setNodeType(2);
treeNode_121.setNodeValue("果实C");
// 节点:122
TreeNode treeNode_122 = new TreeNode();
treeNode_122.setTreeId(10001L);
treeNode_122.setTreeNodeId(122L);
treeNode_122.setNodeType(2);
treeNode_122.setNodeValue("果实D");
// 树根
TreeRoot treeRoot = new TreeRoot();
treeRoot.setTreeId(10001L);
treeRoot.setTreeRootNodeId(1L);
treeRoot.setTreeName("规则决策树");
Map<Long, TreeNode> treeNodeMap = new HashMap<>();
treeNodeMap.put(1L, treeNode_01);
treeNodeMap.put(11L, treeNode_11);
treeNodeMap.put(12L, treeNode_12);
treeNodeMap.put(111L, treeNode_111);
treeNodeMap.put(112L, treeNode_112);
treeNodeMap.put(121L, treeNode_121);
treeNodeMap.put(122L, treeNode_122);
treeRich = TreeRich.builder().treeRoot(treeRoot).treeNodeMap(treeNodeMap).build();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# 3.4.2 执行决策
@Test
public void test_tree() {
IEngine treeEngineHandle = new TreeEngineHandle();
/**
* 测试数据
* 果实A:gender=man、age=22
* 果实B:gender=man、age=29
* 果实C:gender=woman、age=22
* 果实D:gender=woman、age=29
*/
Map<String, String> decisionMatter = new HashMap<>();
//decisionMatter.put("gender", "man");
decisionMatter.put("age", "29");
decisionMatter.put("sg", "170");
EngineResult result = treeEngineHandle.process(10001L, "Oli09pLkdjh", treeRich, decisionMatter);
System.out.println("测试结果" + result.toString());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3.4.3 决策结果
决策树引擎=>规则决策树treeNode:11 ruleKey:SGFilter matterValue:170
决策树引擎=>规则决策树treeNode:112 ruleKey:userAge matterValue:29
测试结果EngineResult(isSuccess=true, userId=Oli09pLkdjh, treeId=10001, nodeId=112, nodeValue=果实B)
1
2
3
2
3
# 4、优点
使用决策树解决大量if..else..堆积问题,拥有高扩展性,在扩展时,仅须关注规则树的定义与决策参数,线信息节点过滤器,引擎引入节点过滤器即可,不需要对原代码更改,代码健壮性更见,不违背开闭原则,不会向if..else堆叠之后修改这导致另外地方不可用问题
