解释器模式
解释器模式
- 解释器模式定义
- 使用场景
- 角色定义
- 1. AbstractExpression--抽象解释器:
- 2. TerminalExpression-终结符表达式:
- 3. NonterminalExpression-一非终结符表达式:
- 4. Context-环境角色:
- 需求背景
- 1. 首先设置一个告警规则
- 2. 定义五种告警的判断规则
- 3. 具体代码
- 3.1 抽象告警规则接口
- 3.2 具体告警规则实现
- 3.3 告警规则解释器
- 3.4 测试案例
- 3.5 测试结果
解释器模式定义
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子
使用场景
- 重复发生的问题可以使用解释器模式
- 一个简单语法需要解释的场景
角色定义
1. AbstractExpression–抽象解释器:
具体的解释任务由各个实现类完成,具体的解释器分别由 TerminalExpression 和 Non-terminalExpression 完成。
2. TerminalExpression-终结符表达式:
实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。
3. NonterminalExpression-一非终结符表达式:
文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
4. Context-环境角色:
一般是用来存放文法中各个终结符所对应的具体值这些信息需要存放到环境角色中,很多情况下我们使用 Map 来充当环境角色就足够了。
需求背景
模拟监控业务系统的运行情况,及时将异常报告发送给开发者,比如,如果每分钟接口出错数超过100,监控系统就通过短信、微信、邮件等方式发送告警给开发者
下面是一个简单的Java示例代码:
1. 首先设置一个告警规则
每分钟API总错数超过100或者每分钟API总调用数超过10000就触发告警
api_error_per_minute > 100 || api_count_per_minute > 10000
2. 定义五种告警的判断规则
||、&&、<、>、==,其中<、>、==运算符的优先级高于||和&&
3. 具体代码
3.1 抽象告警规则接口
public interface Expression {
boolean interpret(Map<String, Long> stats);
}
3.2 具体告警规则实现
public class OrExpression implements Expression {
private List<Expression> expressions = new ArrayList<>();
public OrExpression(List<Expression> expressions) {
this.expressions.addAll(expressions);
}
public OrExpression(String strOrExpression) {
String[] andExpressions = strOrExpression.split("\\|\\|");
for (String andExpression : andExpressions) {
expressions.add(new AndExpression(andExpression));
}
}
@Override
public boolean interpret(Map<String, Long> stats) {
for (Expression expression : expressions) {
if (expression.interpret(stats)) {
return true;
}
}
return false;
}
}
public class AndExpression implements Expression {
private List<Expression> expressions = new ArrayList<>();
public AndExpression(List<Expression> expressions) {
this.expressions.addAll(expressions);
}
public AndExpression(String strAndExpression) {
String[] strExpressions = strAndExpression.split("&&");
for (String strExpression : strExpressions) {
if (strExpression.contains(">")) {
expressions.add(new GreaterExpression(strExpression));
} else if (strExpression.contains("<")) {
expressions.add(new LesserExpression(strExpression));
} else if (strAndExpression.contains("==")) {
expressions.add(new EqualExpression(strExpression));
} else {
throw new RuntimeException("Expression is invalid: " + strAndExpression);
}
}
}
@Override
public boolean interpret(Map<String, Long> stats) {
for (Expression expression : expressions) {
if (!expression.interpret(stats)) {
return false;
}
}
return true;
}
}
public class EqualExpression implements Expression {
private String key;
private Long value;
public EqualExpression(String key, Long value) {
this.key = key;
this.value = value;
}
public EqualExpression(String strExpression) {
String[] elements = strExpression.trim().split("\\s+");
if (elements.length != 3 || !elements[1].trim().equals("==")) {
throw new RuntimeException("Expression is invalid: " + strExpression);
}
this.key = elements[0].trim();
this.value = Long.parseLong(elements[2].trim());
}
@Override
public boolean interpret(Map<String, Long> stats) {
if (!stats.containsKey(key)) {
return false;
}
Long statsValue = stats.get(key);
return statsValue == value;
}
}
public class GreaterExpression implements Expression {
private String key;
private long value;
public GreaterExpression(String key, long value) {
this.key = key;
this.value = value;
}
public GreaterExpression(String strExpression) {
String[] elements = strExpression.trim().split("\\s+");
if (elements.length != 3 || !elements[1].trim().equals(">")) {
throw new RuntimeException("Expression is invalid: " + strExpression);
}
this.key = elements[0].trim();
this.value = Long.parseLong(elements[2].trim());
}
@Override
public boolean interpret(Map<String, Long> stats) {
if (!stats.containsKey(key)) {
return false;
}
Long statValue = stats.get(key);
return statValue > value;
}
}
public class LesserExpression implements Expression {
private String key;
private long value;
public LesserExpression(String key, long value) {
this.key = key;
this.value = value;
}
public LesserExpression(String strExpression) {
String[] elements = strExpression.trim().split("\\s+");
if (elements.length != 3 || !elements[1].trim().equals("<")) {
throw new RuntimeException("Expression is invalid: " + strExpression);
}
this.key = elements[0].trim();
this.value = Long.parseLong(elements[2].trim());
}
@Override
public boolean interpret(Map<String, Long> stats) {
if (!stats.containsKey(key)) {
return false;
}
Long statsValue = stats.get(key);
return statsValue < value;
}
}
3.3 告警规则解释器
public class AlertRuleInterpreter {
private Expression expression;
public AlertRuleInterpreter(String ruleExpression) {
this.expression = new OrExpression(ruleExpression);
}
public boolean interpret(Map<String, Long> stats) {
return expression.interpret(stats);
}
}
3.4 测试案例
@Test
public void test() {
String rule = "api_error_per_minute > 100 || api_count_per_minute > 10000";
AlertRuleInterpreter alertRuleInterpreter = new AlertRuleInterpreter(rule);
HashMap<String, Long> statsMap = new HashMap<>();
statsMap.put("api_error_per_minute", 99l);
statsMap.put("api_count_per_minute", 121l);
boolean alertInterpret = alertRuleInterpreter.interpret(statsMap);
String alert = alertInterpret == true ? "超过阈值,危险!!" : "目前运行良好";
log.info("预警结果为:alert:{}", alert);
}
3.5 测试结果
预警结果为:alert:目前运行良好