设计模式之解释器模式

解释器模式

解释器模式更加小众,只在一些特定的领域会被用到,比如编译器、规则引擎、正则表达式。它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分成一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

定义

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

实现

基于解析器模式的自定义告警规则功能。

1. 定义表达式接口

/**
 * 定义表达式解析模板
 */
public interface Expression {
    /**
     * 对状态进行判断
     * @param stats
     * @return
     */
    boolean interpret(Map<String, Long> stats);
}

2.定义表达式实现类

&&
/**
 * 解析 &&
 * AND的话,需要里面的每个表达式都要满足最后才输出true
 */
public class AndExpression implements Expression {
    private List<Expression> expressions = new ArrayList<>();

    public AndExpression(String strAndExpression) {
        String[] elements = strAndExpression.split("&&");
        for (String element : elements) {
            if (element.contains(">")) {
                expressions.add(new GreaterExpression(element));
            } else if (element.contains("<")) {
                expressions.add(new LessExpression(element));
            } else if (element.contains("==")) {
                expressions.add(new EqualsExpression(element));
            } else {
                throw new RuntimeException("Expression is invalid: " + strAndExpression);
            }
        }
    }

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

    @Override
    public boolean interpret(Map<String, Long> stats) {
        for (Expression expression : expressions) {
            if (!expression.interpret(stats)) {
                return false;
            }
        }
        return true;
    }
}
||
public class OrExpression implements Expression{
    private List<Expression> expressions = new ArrayList<>();
    public OrExpression(String strOrExpression) {
        String[] andExpressions = strOrExpression.split("\\|\\|");
        for (String andExpression : andExpressions) {
            expressions.add(new AndExpression(andExpression));
        }
    }

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

    @Override
    public boolean interpret(Map<String, Long> stats) {
        for (Expression expr : expressions) {
            if (expr.interpret(stats)) {
                return true;
            }
        }
        return false;
    }
}
>
/**
 * 解析 >
 */
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;
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        long statValue = stats.get(key);
        return statValue > value;
    }
}
<
/**
 * 解析 <
 */
public class LessExpression implements Expression{
    private String key;
    private long value;

    public LessExpression(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 LessExpression(String key, long value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        long statValue = stats.get(key);
        return statValue < value;
    }
}
==
/**
 * 解析 ==
 * 单一职责: 只判断key和stats里面的状态是否相等即可
 */
public class EqualsExpression implements Expression{
    private String key;
    private long value;

    public EqualsExpression(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 EqualsExpression(String key, long value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public boolean interpret(Map<String, Long> stats) {
        if (!stats.containsKey(key)) {
            return false;
        }
        long statValue = stats.get(key);
        return statValue == value;
    }
}

3. Main

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);
    }
}
/**
 * 解释器模式的代码比较灵活,没有固定的模板。核心思想是将语法解析的工作拆分到各个小类中,从而避免大而全的解析类。
 * 一般做法是,将语法规则拆分一些小的独立单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析
 */
public class M {
    public static void main(String[] args) {
        String rule = "key1 > 100 && key2 < 30 || key4 == 88";
        AlertRuleInterpreter interpreter = new AlertRuleInterpreter(rule);
        HashMap<String, Long> stats = new HashMap<>(6);
        stats.put("key1", 101L);
        stats.put("key3", 121L);
        stats.put("key4", 88L);

        boolean interpret = interpreter.interpret(stats);
        System.out.println("是否产生预警: " + (interpret ? "产生预警": "未能产生预警"));
    }
}

总结

  1. 解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。
  2. 解释器模式的代码实现比较灵活,没有固定的模板。核心思想是将语法解析的工作拆分到各个小类中,从而避免大而全的解析类。
  3. 一般做法是,将语法规则拆分一些小的独立单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值