解释器模式
解释器模式在我们的开发中并不常见, 它用于用一些固定的语法构建一个解释句子的解释器. 我们常用的正则表达式, 数据库的sql解释器就采用了这种模式.
# 示例
需求: 继续观察者模式中的例子, 完成规则完成规则引擎中的数据匹配部分
需求分析: 我们通常获取到的设备上报的数据都是键值对格式: key=value. 而一次上报数据中可能会包含多组键值对. 规则引擎中的数据匹配其实与SQL解析相似, 循环键值对中各项匹配, 则直接返回true, 执行下一步触发动作.
# 关系运算符类
public enum Operator {
EQUAL(" = "),
GREATER(" > "),
LESS(" < "),
GREATER_EQUAL(" >= "),
LESS_EQUAl(" <= "),
NOT_EQUAL(" <> ");
public final String operator;
Operator(String operator) {
this.operator = operator;
}
}
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
# 连词
public enum Conjunction {
AND(" AND "),
OR(" OR ");
public final String operator;
Conjunction(String operator) {
this.operator = operator;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 表达式
表达式类Expression用于表述要匹配的Key与指定的value之间的关系, 及与其他表达式之间的关系
@Getter
@Setter
class Expression {
// 关系运算符左侧的Key,
private String filed;
// 关系运算符
private Operator operator;
// 关系运算符右侧的value
private String value;
// 关系运算符可能空, 当为空是, 连词应该不为空
// 若存在关系运算符, 则这个Expression仅仅描述的是这个表达式中filed与value之间的关系, 而不是与其他键值对之间的关系
public Expression(String filed, Operator operator, String value) {
this.filed = filed;
this.operator = operator;
this.value = value;
}
// 其他表达式
private List<Expression> expressions;
// 与其他表达式之间的关系 OR 或 AND
private Conjunction conjunction;
// 连词可能为空, 当为空是, 关系运算符应该不为空
// 若存在连词, 则这个Expression描述的是一组表达式之间的关系, 而不是filed与value之间的关系
public Expression(List<Expression> expressions, Conjunction conjunction) {
this.expressions = expressions;
this.conjunction = conjunction;
}
@Override
public String toString() {
if (Objects.nonNull(conjunction)) {
return " ( " + expressions.stream().map(Expression::toString).collect(Collectors.joining(conjunction.operator)) + " ) ";
}
return filed + operator.operator + value;
}
public boolean interpret(Map<String, String> matter) {
// 若存在连词, 则需要依据连词的语义去依次匹配每个表达式
if (Objects.nonNull(conjunction)) {
if (conjunction.equals(Conjunction.AND)) {
for (Expression expression : expressions) {
if (!expression.interpret(matter)){
return false;
}
}
} else {
for (Expression expression : expressions) {
if (expression.interpret(matter)){
return true;
}
}
}
return true;
}
// 不存在连词, 只判断传入的键值对参数之间的关系是否与操作符描述一致即可
return comparing(matter.get(filed));
}
private boolean comparing(String val) {
switch (operator) {
case EQUAL:
return value.equals(val);
case GREATER:
return Double.parseDouble(val) > Double.parseDouble(value);
case LESS_EQUAl:
return Double.parseDouble(val) <= Double.parseDouble(value);
case LESS:
return Double.parseDouble(val) < Double.parseDouble(value);
case GREATER_EQUAL:
return Double.parseDouble(val) >= Double.parseDouble(value);
case NOT_EQUAL:
return Double.parseDouble(val) != Double.parseDouble(value);
default:
return false;
}
}
}
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
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
# 测试
@Test
public void test() {
Expression door = new Expression("门磁", Operator.EQUAL, "开");
Expression flooding = new Expression("水浸", Operator.EQUAL, "开");
Expression vol = new Expression("电压", Operator.LESS, "3");
Expression paramValue = new Expression(newArrayList(door, flooding, vol), Conjunction.OR);
Expression city = new Expression("城市", Operator.EQUAL, "济南");
Expression rule = new Expression(newArrayList(city, paramValue), Conjunction.AND);
System.out.println(rule);
Map<String, String> matter = newHashMap();
matter.put("门磁", "开");
matter.put("水浸", "否");
matter.put("vol", "3.4");
matter.put("城市", "济南");
boolean exec = rule.interpret(matter);
System.out.println(exec); // true
matter.put("城市", "潍坊");
exec = rule.interpret(matter);
System.out.println(exec); // false
}
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