longshu

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

Interpreter 解释器模式

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

  • 结构图:
    Interpreter_structure

  • 示例类图:
    Interpreter_uml

  • 示例代码:

// Expression
public interface Expression {
    public void interpret(Context context);
}

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

posted on 2016-12-29 11:03  longshu  阅读(208)  评论(0编辑  收藏  举报