Skip to content

解释器设计模式在自定义告警规则的应用

概述

Interpreter 模式也叫解释器模式,是行为模式之一,它是一种特殊的设计模式,它建立一个解释器,对于特定的计算机程序设计语言,用来解释预先定义的文法。简单地说,Interpreter 模式是一种简单的语法解释器构架。 换一种解释就是定义一个语法, 定义一个解释器,该解释器处理该语法句子将某些复杂问题,表达为某种语法规则,然后构建解释器来解释处理这类句子。

角色

  1. Expression(抽象表达式) 声明一个抽象的解释操作。

  2. TerminalExpression(终结符表达式) 实现与文法中的终结符相关联的解释操作

  3. NonterminalExpression(非终结符表达式) 为文法中的非终结符实现解释(Interpret)操作。

  4. Context(上下文) 包含解释器之外的一些全局信息。

  5. Client(客户)构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树

应用场景

  1. 风控系统中的配置规则报警
  2. 物联网健康数据监控

案例

在处理大健康医疗系统的时候,我们通常会对每一个用户进行单独的健康指标设置,对应的设备上报的数据要是符合不符合我们的指标,那么我们就会进行对应的事件处理,这个场景就很符合采用解释器设计模式,以下代码是我经过一些简化,保留解释器设计模式的核心代码

定义 Expression

java
public interface Expression {

    boolean Interpret(Map<String,Long> param);

}

定义表达式

java
public class GreaterExpression implements Expression {
    private final String key;
    private final Long value;
    public GreaterExpression(String expression) {
        String[] elements = expression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals(">")) {
            throw new UnsupportedOperationException("表达式不正确 " + expression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }
    @Override
    public boolean Interpret(Map<String,Long> param) {
        if (!param.containsKey(key)) {
            return false;
        }
        Long targetValue = param.get(key);
        return targetValue > value;
    }
}

public class LessExpression implements Expression{

    private final String key;

    private final Long value;

    public LessExpression(String expression) {
        String[] elements = expression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals("<")) {
            throw new UnsupportedOperationException("表达式不正确 " + expression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }

    @Override
    public boolean Interpret(Map<String,Long> params) {
        if (!params.containsKey(key)) {
            return false;
        }
        return params.get(key) < this.value;
    }
}

public class EqualExpression implements Expression{

    private final String key;

    private final Long value;

    public EqualExpression(String expression) {
        String[] elements = expression.trim().split("\\s+");
        if (elements.length != 3 || !elements[1].trim().equals("==")) {
            throw new UnsupportedOperationException("表达式不正确 " + expression);
        }
        this.key = elements[0].trim();
        this.value = Long.parseLong(elements[2].trim());
    }

    @Override
    public boolean Interpret(Map<String,Long> params) {
        if (!params.containsKey(key)){
            return false;
        }
        return params.get(key).equals(this.value);
    }
}

public class AndExpression implements Expression{

    private List<Expression> expressions = new ArrayList<>();

    public AndExpression(String expression) {
        String[] splitExpressions = expression.split("&&");
        for (String expr : splitExpressions) {
            if (expr.contains(">")) {
                expressions.add(new GreaterExpression(expr));
            } else if (expr.contains("<")) {
                expressions.add(new LessExpression(expr));
            } else if (expr.contains("==")) {
                expressions.add(new EqualExpression(expr));
            } else {
                throw new UnsupportedOperationException("不支持的类型: " + expr);
            }
        }
    }

    public AndExpression(List<Expression> expressions) {
        this.expressions.addAll(expressions);
    }

    @Override
    public boolean Interpret(Map<String,Long> params) {
        for (Expression expression : expressions) {
            if (!expression.Interpret(params)) {
                return false;
            }
        }
        return true;
    }
}

public class OrExpression implements Expression{
    private List<Expression> expressions = new ArrayList<>();

    public OrExpression(String expression) {
        String[] splitExpressions = expression.split("\\|\\|");
        for (String expr : splitExpressions) {
            if (expr.contains(">")) {
                expressions.add(new GreaterExpression(expr));
            } else if (expr.contains("<")) {
                expressions.add(new LessExpression(expr));
            } else if (expr.contains("==")) {
                expressions.add(new EqualExpression(expr));
            } else {
                throw new UnsupportedOperationException("不支持的类型: " + expr);
            }
        }
    }

    public OrExpression(List<Expression> expressions) {
        this.expressions.addAll(expressions);
    }

    @Override
    public boolean Interpret(Map<String,Long> params) {
        for (Expression expression : expressions) {
            if (expression.Interpret(params)) {
                return true;
            }
        }
        return false;
    }
}

定义 Conetext 对象

java
public class AlarmRuleInterpreter {

    private Expression expression;

    public AlarmRuleInterpreter(Expression expression) {
        this.expression = expression;
    }

    public boolean Interpret(Map<String,Long> params) {
        return this.expression.Interpret(params);
    }

    public void setExpression(Expression expression) {
        this.expression = expression;
    }

}

测试

java
public class Client {

    public static void main(String[] args) {

        GreaterExpression greaterExpression = new GreaterExpression("heartRate > 60");
        AlarmRuleInterpreter alarmRuleInterpreter = new AlarmRuleInterpreter(greaterExpression);
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate", 70L)));
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate", 60L)));

        LessExpression lessExpression = new LessExpression("heartRate < 70");
        alarmRuleInterpreter.setExpression(lessExpression);
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate",60L)));
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate",71L)));


        EqualExpression equalExpression = new EqualExpression("heartRate == 70");
        alarmRuleInterpreter.setExpression(equalExpression);
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate",60L)));
        System.out.println(alarmRuleInterpreter.Interpret(Map.of("heartRate",70L)));


        AndExpression andExpression = new AndExpression("SBP > 90 && SBP < 140 && DBP > 60 && DBP < 90");
        alarmRuleInterpreter.setExpression(andExpression);
        System.out.println("AND " + alarmRuleInterpreter.Interpret(Map.of("SBP", 120L, "DBP", 80L)));
        System.out.println("AND " + alarmRuleInterpreter.Interpret(Map.of("SBP", 120L, "DBP", 100L)));

        OrExpression orExpression = new OrExpression("SBP > 90 || SBP < 140 || DBP > 60 || DBP < 90");
        alarmRuleInterpreter.setExpression(orExpression);
        System.out.println("or " + alarmRuleInterpreter.Interpret(Map.of("SBP", 120L, "DBP", 80L)));

    }
}

Released under the MIT License.