0%

设计模式-解释器模式

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

优点:

  • 将每个语法规则表示成一个类,方便实现语言。
  • 因为语法由许多类表示,可以轻易改变或拓展此语言。
  • 通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如复杂的程序验证等。

缺点:

  • 当语法规则的数目太大时,这个模式可能会变得非常复杂。

类图

  • Context:包含解释器之外的一些全局信息,可以是正在解析的语言字符串输入流
  • AbstractExpression:抽象表达式,声明一个抽象的解释操作
  • Client:客户端代码,构建表示该文法定义的语言中一个特定句子的抽象语法树

3MIIXt.md.png

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Context {

private String input;
private String output;

public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}

}
1
2
3
4
5
public abstract class AbstractExpression {

public abstract void interprete(Context context);

}
1
2
3
4
5
6
7
8
public class TerminalExpression extends AbstractExpression {

@Override
public void interprete(Context context) {
System.out.println("终端解释器");
}

}
1
2
3
4
5
6
7
8
public class NonTerminalExpression extends AbstractExpression {

@Override
public void interprete(Context context) {
System.out.println("非终端解释器");
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.ArrayList;
import java.util.List;

public class Client {

public static void main(String[] args) {
Context context = new Context();
List<AbstractExpression> list = new ArrayList<AbstractExpression>();
list.add(new TerminalExpression());
list.add(new NonTerminalExpression());
list.add(new TerminalExpression());

for(AbstractExpression exp: list) {
exp.interprete(context);
}
}

}

例:实现A&&B,A和B只能是布尔型:true和false

1
2
3
4
5
public abstract class Expression {

public abstract boolean interpret(String info);

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TerminalExpression extends Expression {

@Override
public boolean interpret(String info) {
if (info.equals("true")) {
return true;
} else if (info.equals("false")) {
return false;
} else {
throw new RuntimeException("不合法的表达式");
}
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AndExpression extends Expression {

private Expression exp1;
private Expression exp2;

public AndExpression(Expression exp1, Expression exp2) {
this.exp1 = exp1;
this.exp2 = exp2;
}

@Override
public boolean interpret(String info) {
String[] strings = info.split("&&");
return exp1.interpret(strings[0]) && exp2.interpret(strings[1]);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Context {

private Expression expression;

public Context() {
Expression exp1 = new TerminalExpression();
Expression exp2 = new TerminalExpression();
expression = new AndExpression(exp1, exp2);
}

public boolean getResult(String info) {
boolean res = expression.interpret(info);
return res;
}

}
1
2
3
4
5
6
7
8
9
public class Client {

public static void main(String[] args) {
Context context = new Context();
boolean res = context.getResult("true&&true");
System.out.println(res);
}

}