解釋器模式是一種行為型模式锄贼,它的主要作用是用一種方式來實(shí)現(xiàn)對(duì)表達(dá)式或文法的處理票灰。我們可以使用解釋器模式處理語言的解析,在設(shè)計(jì)計(jì)算機(jī)語言的時(shí)候解釋器模式很有用處宅荤。
解釋器模式可能需要用到一點(diǎn)編譯原理的知識(shí)米间。不過我自己編譯原理的內(nèi)容都忘光了,所以這里不做編譯原理的任何介紹了膘侮。直接來看代碼吧屈糊。我們來做一個(gè)不含括號(hào)的四則運(yùn)算的解釋器。
解釋器模式首先需要一個(gè)表達(dá)式接口琼了,其中有一個(gè)方法用于解析表達(dá)式的值逻锐。
public interface Expression {
int interpret(Context context);
}
之后來考慮一些具體的表達(dá)式夫晌。首先是常量表達(dá)式,這個(gè)很簡(jiǎn)單昧诱,直接返回常量的值即可晓淀。
class Constant implements Expression {
private int i;
public Constant(int i) {
this.i = i;
}
@Override
public int interpret(Context context) {
return i;
}
}
然后是變量,變量的值保存在上下文中盏档,在編譯領(lǐng)域也可以叫做符號(hào)表之類的凶掰,反正都是一個(gè)意思。
class Variable implements Expression {
@Override
public int interpret(Context context) {
return context.getValue(this);
}
}
上下文蜈亩,或者叫符號(hào)表懦窘,是保存變量值的地方。我們?cè)贘ava中可以簡(jiǎn)單的使用Map來當(dāng)做符號(hào)表稚配。
public class Context {
private HashMap<Variable, Integer> map = new HashMap<>();
public void putValue(Variable name, int value) {
map.put(name, value);
}
public int getValue(Variable name) {
return map.get(name);
}
}
然后是加減乘除四種表達(dá)式畅涂。這個(gè)非常簡(jiǎn)單,沒啥說的吧道川。
class Add implements Expression {
private Expression a, b;
public Add(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) + b.interpret(context);
}
}
class Sub implements Expression {
private Expression a, b;
public Sub(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) - b.interpret(context);
}
}
class Mul implements Expression {
private Expression a, b;
public Mul(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) * b.interpret(context);
}
}
class Div implements Expression {
private Expression a, b;
public Div(Expression a, Expression b) {
this.a = a;
this.b = b;
}
@Override
public int interpret(Context context) {
return a.interpret(context) / b.interpret(context);
}
}
這些類都準(zhǔn)備好之后午衰,我們就可以測(cè)試一下解釋器模式了。我們手動(dòng)創(chuàng)建一個(gè)表達(dá)式冒萄,然后調(diào)用它的interpret()
方法對(duì)其求值臊岸。之后疮茄,表達(dá)式就會(huì)如我們所愿的給出結(jié)果持钉。
public void run() {
Variable a = new Variable();
Variable b = new Variable();
Context context = new Context();
context.putValue(a, 3);
context.putValue(b, 4);
//a+b*(a-b)+2
Expression expression = new Add(a, new Add(new Mul(b, new Sub(a, b)), new Constant(2)));
System.out.println("a+b*(a-b)+2=" + expression.interpret(context));
}
當(dāng)然,這只是一個(gè)非常簡(jiǎn)單的小例子椎椰,因?yàn)?code>new Add(a, new Add(new Mul(b, new Sub(a, b)), new Constant(2)))這個(gè)表達(dá)式樹是我們手動(dòng)創(chuàng)建的奠旺。如果我們希望更加實(shí)用的話蜘澜,就需要自己編寫程序施流,解析字符串响疚,然后轉(zhuǎn)換為抽象語法樹。這就屬于編譯原理的話題了瞪醋。