当前位置: 首页 > article >正文

解释器模式

解释器模式

  • 解释器模式定义
    • 使用场景
    • 角色定义
      • 1. AbstractExpression--抽象解释器:
      • 2. TerminalExpression-终结符表达式:
      • 3. NonterminalExpression-一非终结符表达式:
      • 4. Context-环境角色:
    • 需求背景
      • 1. 首先设置一个告警规则
      • 2. 定义五种告警的判断规则
      • 3. 具体代码
        • 3.1 抽象告警规则接口
        • 3.2 具体告警规则实现
        • 3.3 告警规则解释器
        • 3.4 测试案例
        • 3.5 测试结果

解释器模式定义

给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子

使用场景

  1. 重复发生的问题可以使用解释器模式
  2. 一个简单语法需要解释的场景

角色定义

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:目前运行良好

http://www.kler.cn/a/17672.html

相关文章:

  • llama factory lora 微调 qwen2.5 7B Instruct模型
  • Git在版本控制中的应用
  • Java 责任链模式 减少 if else 实战案例
  • 批量重命名Excel文件并排序
  • change buffer:到底应该选择普通索引还是唯一索引
  • makefile 设置动态库路径参数
  • Unity 过场工具(Cutscene)设计(三)
  • 2023.5.7 第五十二次周报
  • B019_子查询篇
  • 从五一的旅游热潮看,该如何实现数字文旅的转型升级?
  • 浅聊一下cmake
  • 降维算法详解:理论及示例代码实现
  • 自学SQL入门(2)
  • 如何写出高质量代码
  • UG NX二次开发(C++)-用UF_OBJ_cycle_objs_in_part遍历对象
  • 顺序表的基本操作(初始化,增,删,查,改等等)
  • 【c语言】字符串匹配(搜索) | API仿真
  • Nginx快速入门
  • I.MX6Q-SDB开发板移植ubuntu
  • MySQL5.7和MySQL8.0的区别是什么
  • 华为OD机试 - 优选核酸检测点(Python)
  • 操作系统(2.7)--进程
  • DAY 55 mysql数据库管理
  • 计算机专业还有前途吗?从业9年的程序员告诉你优缺点
  • MySQL知识学习04(MySQL事务隔离级别详解)
  • Elasticsearch --- 数据同步、集群