24.Interpreter-解释器模式

来源:互联网 发布:陈舜臣 知乎 编辑:程序博客网 时间:2024/05/29 05:01

Interpreter 解释器模式

  • 解释器模式:
    定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。
    解释器模式是一种类行为型模式。 由于表达式可分为终结符表达式和非终结符表达式,
    因此解释器模式的结构与组合模式的结构有些类似,但在解释器模式中包含更多的组成元素。

  • 结构图:
    Interpreter_structure

  • 示例类图:
    Interpreter_uml

  • 示例代码:

// Expressionpublic interface Expression {    public void interpret(Context context);}// AbstractExpressionpublic abstract class AbstractExpression implements Expression {    protected static List<String> table;    public AbstractExpression() {        if (null == table) {            initTable();        }    }    public void initTable() {        table = new ArrayList<String>();        table.add("一");        table.add("二");        table.add("三");        table.add("四");        table.add("五");        table.add("六");        table.add("七");        table.add("八");        table.add("九");    }    public void interpret(Context context) {        String statement = context.getStatement();        System.out.println(statement);        if (null == statement || statement.isEmpty())            return;        for (int i = 0; i < table.size(); i++) {            String tail = table.get(i) + this.getPostfix();            // 从低位往高位分析,即从右往左            if (statement.endsWith(tail)) {                int newData = context.getData() + (i + 1) * this.multiplier();                context.setData(newData);                context.setStatement(statement.substring(0, statement.length() - tail.length()));            }            if (statement.endsWith("零")) {                context.setStatement(statement.substring(0, statement.length() - "零".length()));            }        }    }    // 表达式的后缀是以什么表示的 十,百,千...    public abstract String getPostfix();    // 表达式的数量级    public abstract int multiplier();}// TerminalExpression 个位数解释器public class ExpressionGe extends AbstractExpression {    @Override    public String getPostfix() {        return "";    }    @Override    public int multiplier() {        return 1;    }}// TerminalExpression 十位数解释器public class ExpressionShi extends AbstractExpression {    @Override    public String getPostfix() {        return "十";    }    @Override    public int multiplier() {        return 10;    }}// TerminalExpression 百位数解释器public class ExpressionBai extends AbstractExpression {    @Override    public String getPostfix() {        return "百";    }    @Override    public int multiplier() {        return 100;    }}// TerminalExpression 千位数解释器public class ExpressionQian extends AbstractExpression {    @Override    public String getPostfix() {        return "千";    }    @Override    public int multiplier() {        return 1000;    }}// NonterminalExpression 万位数解释器public class ExpressionWan extends AbstractExpression {    private static List<Expression> expressions = new ArrayList<Expression>();    public ExpressionWan() {        if (expressions.isEmpty()) {            expressions.add(new ExpressionGe());            expressions.add(new ExpressionShi());            expressions.add(new ExpressionBai());            expressions.add(new ExpressionQian());        }    }    @Override    public void interpret(Context context) {        String statement = context.getStatement();        if (null == statement || statement.isEmpty())            return;        if (statement.endsWith(this.getPostfix())) {            context.setStatement(statement.substring(0, statement.length() - getPostfix().length()));            int data = context.getData();            context.setData(0);// 置零            for (Expression expression : expressions) {                expression.interpret(context);            }            context.setData(data + this.multiplier() * context.getData());        }    }    @Override    public String getPostfix() {        return "万";    }    @Override    public int multiplier() {        return 10000;    }}// 将中文数字串由低位向高位方向不断转化public class Convertor {    private static List<Expression> expressions = new ArrayList<Expression>();    public Convertor() {        if (expressions.isEmpty()) {            expressions.add(new ExpressionGe());            expressions.add(new ExpressionShi());            expressions.add(new ExpressionBai());            expressions.add(new ExpressionQian());            expressions.add(new ExpressionWan());        }    }    public int convert(String chineseNum) {        Context context = new Context(chineseNum);        for (Expression expression : expressions) {            expression.interpret(context);        }        return context.getData();    }}// 测试public class ExpressionTest {    public static void main(String[] args) {        String chineseNum = "六百三十七万八千二百零一";// 6378201        Convertor convertor = new Convertor();        System.out.println(chineseNum);        System.out.println(convertor.convert(chineseNum));        System.out.println(convertor.convert("五百万"));    }}
  1. Context:上下文,通常包含各个解释器需要的数据或是公共的功能。
    这个Context在解释器模式中起着非常重要的作用。
    一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

  2. AbstractExpression: 定义解释器的接口/抽象类,约定解释器的解释操作。
    其中的Interpret接口,正如其名字那样,它是专门用来解释该解释器所要实现的功能。
    (如加法解释器中的Interpret接口就是完成两个操作数的相加功能)。

  3. TerminalExpression: 终结符解释器,用来实现语法规则中和终结符相关的操作,
    不再包含其他的解释器,如果用组合模式来构建抽象语法树的话,
    就相当于组合模式中的叶子对象,可以有多种终结符解释器。

  4. NonterminalExpression: 非终结符解释器,用来实现语法规则中非终结符相关的操作,
    通常一个解释器对应一个语法规则,可以包含其他解释器,如果用组合模式构建抽象语法树的话,
    就相当于组合模式中的组合对象。可以有多种非终结符解释器。

    • 缺点:
  5. 执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,
    因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

  6. 对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,
    因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,
    此时可以考虑使用语法分析程序等方式来取代解释器模式。

0 0