设计模式学习(二十二):解释器模式
admin
2024-01-20 19:51:43
0

设计模式学习(二十二):解释器模式

作者:Grey

原文地址:

博客园:设计模式学习(二十二):解释器模式

CSDN:设计模式学习(二十二):解释器模式

解释器模式

解释器模式是一种行为型模式。

解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。

一般用于脚本语言解释器。

示例:如何实现一个自定义接口告警规则功能?

一般来讲,监控系统支持开发者自定义告警规则,比如我们可以用下面这样一个表达式,来表示一个告警规则,它表达的意思是:每分钟 API 总出错数超过 100 或者每分钟 API 总调用数超过 10000 就触发告警。

api_error_per_minute > 100 || api_count_per_minute > 10000

在监控系统中,告警模块只负责根据统计数据和告警规则,判断是否触发告警。至于每分钟 API 接口出错数、每分钟接口调用数等统计数据的计算,是由其他模块来负责的。其他模块将统计数据放到一个 Map 中(数据的格式如下所示),发送给告警模块。接下来,我们只关注告警模块。

Map apiStat = new HashMap<>();
apiStat.put("api_error_per_minute", 103);
apiStat.put("api_count_per_minute", 987);

为了简化讲解和代码实现,我们假设自定义的告警规则只包含||、&&、>、<、==这五个运算符,其中,>、<、==运算符的优先级高于||、&&运算符,&&运算符优先级高于||。在表达式中,任意元素之间需要通过空格来分隔。除此之外,用户可以自定义要监控的 key,比如前面的 api_error_per_minute、api_count_per_minute。


public class AlertRuleInterpreter {// key1 > 100 && key2 < 1000 || key3 == 200public AlertRuleInterpreter(String ruleExpression) {//TODO:由你来完善}// apiStat = new HashMap<>();//apiStat.put("key1", 103);//apiStat.put("key2", 987);public boolean interpret(Map stats) {//TODO:由你来完善}}public class DemoTest {public static void main(String[] args) {String rule = "key1 > 100 && key2 < 30 || key3 < 100 || key4 == 88";AlertRuleInterpreter interpreter = new AlertRuleInterpreter(rule);Map stats = new HashMap<>();stats.put("key1", 101l);stats.put("key3", 121l);stats.put("key4", 88l);boolean alert = interpreter.interpret(stats);System.out.println(alert);}
}

实际上,我们可以把自定义的告警规则,看作一种特殊“语言”的语法规则。我们实现一个解释器,能够根据规则,针对用户输入的数据,判断是否触发告警。利用解释器模式,我们把解析表达式的逻辑拆分到各个小类中,避免大而复杂的大类的出现。


public interface Expression {boolean interpret(Map stats);
}public class GreaterExpression implements Expression {private String key;private long 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());}public GreaterExpression(String key, long value) {this.key = key;this.value = value;}@Overridepublic boolean interpret(Map stats) {if (!stats.containsKey(key)) {return false;}long statValue = stats.get(key);return statValue > value;}
}// LessExpression/EqualExpression跟GreaterExpression代码类似,这里就省略了
public class AndExpression implements Expression {private List expressions = new ArrayList<>();public AndExpression(String strAndExpression) {String[] strExpressions = strAndExpression.split("&&");for (String strExpr : strExpressions) {if (strExpr.contains(">")) {expressions.add(new GreaterExpression(strExpr));} else if (strExpr.contains("<")) {expressions.add(new LessExpression(strExpr));} else if (strExpr.contains("==")) {expressions.add(new EqualExpression(strExpr));} else {throw new RuntimeException("Expression is invalid: " + strAndExpression);}}}public AndExpression(List expressions) {this.expressions.addAll(expressions);}@Overridepublic boolean interpret(Map stats) {for (Expression expr : expressions) {if (!expr.interpret(stats)) {return false;}}return true;}}public class OrExpression implements Expression {private List expressions = new ArrayList<>();public OrExpression(String strOrExpression) {String[] andExpressions = strOrExpression.split("\\|\\|");for (String andExpr : andExpressions) {expressions.add(new AndExpression(andExpr));}}public OrExpression(List expressions) {this.expressions.addAll(expressions);}@Overridepublic boolean interpret(Map stats) {for (Expression expr : expressions) {if (expr.interpret(stats)) {return true;}}return false;}
}public class AlertRuleInterpreter {private Expression expression;public AlertRuleInterpreter(String ruleExpression) {this.expression = new OrExpression(ruleExpression);}public boolean interpret(Map stats) {return expression.interpret(stats);}
} 

解释器模式的应用

  • Spring 中的 ExpressionParser

UML 和 代码

UML 图

代码

更多

设计模式学习专栏

参考资料

  • 极客时间-设计模式之美-王争

  • Head First 设计模式

  • 设计模式-可复用面向对象软件的基础

  • 坦克大战-马士兵

  • 菜鸟教程-设计模式

相关内容

热门资讯

我很爱他!日日夜夜的想他,怎么... 我很爱他!日日夜夜的想他,怎么办?我活的很累!!.从你说的来看,你需要冷静一点,太依赖不好.可能时间...
全球开园规模最大乐高乐园在上海... 作为全球开园规模最大的乐高乐园,上海乐高乐园5日正式开园。 业界人士认为,国际知名主题乐园相继加码布...
拜年的来历? 拜年的来历?那你是卖。... 那你是卖。 展开 传说远古时代有一种叫“年”的怪物,每逢腊月三十...
工作压力有利于成长的事例 工作压力有利于成长的事例 把李嘉诚的传记,推荐给您,我以前看过一多半,很有感触,希望可以帮助到您
苏武牧羊北海边的北海指的是哪里... 苏武牧羊北海边的北海指的是哪里?贝加尔湖,中国古代称为北海,位于俄罗斯西伯利亚南部简介贝加尔湖是亚欧...
购物狂电影的最后一幕那个弃婴 ... 购物狂电影的最后一幕那个弃婴 是怎么回事?是主角的小时候吧,讲她为什么是购物狂,因为她小时候被抛弃在...
方法决定成败 方法决定成败没错,方法决定成败,态度决定一切,心态决定效率。送你这几句名言,以资鼓励。
霞秋的意思?想表达晚年幸福? 霞秋的意思?想表达晚年幸福?霞秋的意思?想表达晚年幸福?... 霞秋的意思?想表达晚年幸福? 展...
关于“欣赏”的名言和事例 关于“欣赏”的名言和事例19世纪末,美国西部的密苏里有一个坏孩子,他偷偷地向邻居家的窗户扔石头,还把...
自己发的语音总是不敢去听,怎么... 自己发的语音总是不敢去听,怎么让自己勇敢去听呢?怎么说呢,其实你录下来的声音就是别人听到的,只是因为...
格物致知的真正意义是什么? 格物致知的真正意义是什么?提示:可以从文章内容中直接找到答案。? 参考答案:格物致知的真正...
醒悟中心卢卫斌老师谈强迫症的治... 醒悟中心卢卫斌老师谈强迫症的治疗为什么需要禅修练习  强迫症是一种复合型心理障碍,有其独特的障碍模型...
宣化那有好玩的地方 宣化那有好玩的地方有吗? 「莫等闲,白了少年头。空b切」
水深水浅东西涧 云去云来远近山... 水深水浅东西涧 云去云来远近山是什么意思  涧水或东或西时深时浅,山峦亦近云雾盘桓.  作品原文  ...
我的妹妹不可能那么可爱 讲的是... 我的妹妹不可能那么可爱 讲的是什么?就是有一个长的很可爱明明可以很受欢迎【也确实很受欢迎】的妹纸爱好...
童话诗有什么特点 童话诗有什么特点 童话诗(Fairy tale poem),故事诗的一种,现代诗的一种体裁。是以童话...
一块姜在挡车的是什么歌 一块姜在挡车的是什么歌一块姜在挡车的是什么歌感应:泳儿的歌我听的不多,但这首歌尤其的熟悉是一个人生活...
MP3出问题 MP3出问题我选其他歌,它都会跳回去原来那首歌,有时候还更厉害,显示这首歌的文件名字,唱另外一首歌出...
在金庸的设定里,一个武林高手可... 在金庸的设定里,一个武林高手可以打赢100个人已经是极限,但500个武林高手一定打不过1000名普第...
唐诗人张九龄"海上生明月天涯天... 唐诗人张九龄"海上生明月天涯天涯共此时"一诗全文?望月汪渗怀远 唐· 张九龄海上生明月,天涯共此时。...