Interpreter 解释器模式
解释器模式:
定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。
解释器模式是一种类行为型模式。 由于表达式可分为终结符表达式和非终结符表达式,
因此解释器模式的结构与组合模式的结构有些类似,但在解释器模式中包含更多的组成元素。结构图:
示例类图:
示例代码:
// 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("五百万"));
}
}
Context:上下文,通常包含各个解释器需要的数据或是公共的功能。
这个Context在解释器模式中起着非常重要的作用。
一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。AbstractExpression: 定义解释器的接口/抽象类,约定解释器的解释操作。
其中的Interpret接口,正如其名字那样,它是专门用来解释该解释器所要实现的功能。
(如加法解释器中的Interpret接口就是完成两个操作数的相加功能)。TerminalExpression: 终结符解释器,用来实现语法规则中和终结符相关的操作,
不再包含其他的解释器,如果用组合模式来构建抽象语法树的话,
就相当于组合模式中的叶子对象,可以有多种终结符解释器。NonterminalExpression: 非终结符解释器,用来实现语法规则中非终结符相关的操作,
通常一个解释器对应一个语法规则,可以包含其他解释器,如果用组合模式构建抽象语法树的话,
就相当于组合模式中的组合对象。可以有多种非终结符解释器。- 缺点:
执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,
因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,
因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,
此时可以考虑使用语法分析程序等方式来取代解释器模式。