解释器模式

一、解释器模式定义

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

1. 使用场景

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

2. 角色定义

1. AbstractExpression–抽象解释器:

具体的解释任务由各个实现类完成,具体的解释器分别由 TerminalExpression 和 Non-terminalExpression 完成。

2. TerminalExpression-终结符表达式:

实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。

3. NonterminalExpression-一非终结符表达式:

文法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。

4. Context-环境角色:

一般是用来存放文法中各个终结符所对应的具体值这些信息需要存放到环境角色中,很多情况下我们使用 Map 来充当环境角色就足够了。

3. 需求背景

模拟监控业务系统的运行情况,及时将异常报告发送给开发者,比如,如果每分钟接口出错数超过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:目前运行良好

4. 小结

  • 解释器模式是一种行为型设计模式,它定义了一种语言解释器的结构,用于解释和执行特定的语言表达式。

  • 解释器模式由抽象表达式(AbstractExpression)、终结符表达式(TerminalExpression)、非终结符表达式(NonterminalExpression)、上下文(Context)和客户端(Client)等角色组成。

  • 抽象表达式定义了解释器的接口,其中包括一个解释方法interpret(),是解释器模式的核心方法。终结符表达式代表语言中的基本元素,它实现了解释方法,用于解释和执行特定的语言表达式。非终结符表达式代表语言中的组合元素,它也实现了解释方法,用于解释和执行复杂的语言表达式。上下文对象存储解释器解释时的状态信息。客户端创建并配置解释器对象,然后调用解释方法解释和执行语言表达式。

  • 使用解释器模式可以实现简单的语言解释器,将语言表达式转化为特定的操作。它能够灵活地扩展和修改语言的语法规则,使得解释器可以解释和执行不同的语言表达式。同时,解释器模式也可以用于构建领域特定语言(DSL),用于描述和处理特定领域的问题。

  • 总结来说,解释器模式是一种用于解释和执行语言表达式的设计模式,它能够实现灵活的语法扩展和修改,并且可以用于构建领域特定语言。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Run,boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值