解釋器模式在我看來,應(yīng)用范圍很小,我想了很久,想舉一個不是加減乘除運算的例子出來,但是很難......在設(shè)計模式一書中,它的意圖也被定義為實現(xiàn)一種語言所要運用的模式,我在網(wǎng)上找了一篇比較容易理解的文章,在此貼出來供大家閱讀。http://www.jb51.net/article/79590.htm
這篇文章主要介紹了解析Java的設(shè)計模式編程之解釋器模式的運用,文中對解釋器模式的優(yōu)缺點及適用場景作出了分析,需要的朋友可以參考下
定義:給定一種語言,定義他的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中句子。
類型:行為類模式
類圖:

解釋器模式是一個比較少用的模式,本人之前也沒有用過這個模式。下面我們就來一起看一下解釋器模式。
解釋器模式的結(jié)構(gòu) 抽象解釋器:聲明一個所有具體表達式都要實現(xiàn)的抽象接口(或者抽象類),接口中主要是一個interpret()方法,稱為解釋操作。具體解釋任務(wù)由它的各個實現(xiàn)類來完成,具體的解釋器分別由終結(jié)符解釋器TerminalExpression和非終結(jié)符解釋器NonterminalExpression完成。
終結(jié)符表達式:實現(xiàn)與文法中的元素相關(guān)聯(lián)的解釋操作,通常一個解釋器模式中只有一個終結(jié)符表達式,但有多個實例,對應(yīng)不同的終結(jié)符。終結(jié)符一半是文法中的運算單元,比如有一個簡單的公式R=R1+R2,在里面R1和R2就是終結(jié)符,對應(yīng)的解析R1和R2的解釋器就是終結(jié)符表達式。
非終結(jié)符表達式:文法中的每條規(guī)則對應(yīng)于一個非終結(jié)符表達式,非終結(jié)符表達式一般是文法中的運算符或者其他關(guān)鍵字,比如公式R=R1+R2中,+就是非終結(jié)符,解析+的解釋器就是一個非終結(jié)符表達式。非終結(jié)符表達式根據(jù)邏輯的復(fù)雜程度而增加,原則上每個文法規(guī)則都對應(yīng)一個非終結(jié)符表達式。
環(huán)境角色:這個角色的任務(wù)一般是用來存放文法中各個終結(jié)符所對應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環(huán)境角色中,很多情況下我們使用Map來充當環(huán)境角色就足夠了。
例子 來舉一個加減乘除的例子吧,實現(xiàn)思路來自于《java與模式》中的例子。每個角色的功能按照上面提到的規(guī)范來實現(xiàn)。
//上下文(環(huán)境)角色,使用HashMap來存儲變量對應(yīng)的數(shù)值
class Context
{
private Map valueMap = new HashMap();
public void addValue(Variable x , int y)
{
Integer yi = new Integer(y);
valueMap.put(x , yi);
}
public int LookupValue(Variable x)
{
int i = ((Integer)valueMap.get(x)).intValue();
return i ;
}
}
//抽象表達式角色,也可以用接口來實現(xiàn)
abstract class Expression
{
public abstract int interpret(Context con);
}
//終結(jié)符表達式角色
class Constant extends Expression
{
private int i ;
public Constant(int i)
{
this.i = i;
}
public int interpret(Context con)
{
return i ;
}
}
class Variable extends Expression
{
public int interpret(Context con)
{
//this為調(diào)用interpret方法的Variable對象
return con.LookupValue(this);
}
}
//非終結(jié)符表達式角色
class Add extends Expression
{
private Expression left ,right ;
public Add(Expression left , Expression right)
{
this.left = left ;
this.right= right ;
}
public int interpret(Context con)
{
return left.interpret(con) + right.interpret(con);
}
}
class Subtract extends Expression
{
private Expression left , right ;
public Subtract(Expression left , Expression right)
{
this.left = left ;
this.right= right ;
}
public int interpret(Context con)
{
return left.interpret(con) - right.interpret(con);
}
}
class Multiply extends Expression
{
private Expression left , right ;
public Multiply(Expression left , Expression right)
{
this.left = left ;
this.right= right ;
}
public int interpret(Context con)
{
return left.interpret(con) * right.interpret(con);
}
}
class Division extends Expression
{
private Expression left , right ;
public Division(Expression left , Expression right)
{
this.left = left ;
this.right= right ;
}
public int interpret(Context con)
{
try{
return left.interpret(con) / right.interpret(con);
}catch(ArithmeticException ae)
{
System.out.println("被除數(shù)為0!");
return -11111;
}
}
}
//測試程序,計算 (a*b)/(a-b+2)
public class Test
{
private static Expression ex ;
private static Context con ;
public static void main(String[] args)
{
con = new Context();
//設(shè)置變量、常量
Variable a = new Variable();
Variable b = new Variable();
Constant c = new Constant(2);
//為變量賦值
con.addValue(a , 5);
con.addValue(b , 7);
//運算,對句子的結(jié)構(gòu)由我們自己來分析,構(gòu)造
ex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c));
System.out.println("運算結(jié)果為:"+ex.interpret(con));
}
}
解釋器模式的優(yōu)缺點 解釋器是一個簡單的語法分析工具,它最顯著的優(yōu)點就是擴展性,修改語法規(guī)則只需要修改相應(yīng)的非終結(jié)符就可以了,若擴展語法,只需要增加非終結(jié)符類就可以了。
但是,解釋器模式會引起類的膨脹,每個語法都需要產(chǎn)生一個非終結(jié)符表達式,語法規(guī)則比較復(fù)雜時,就可能產(chǎn)生大量的類文件,為維護帶來非常多的麻煩。同時,由于采用遞歸調(diào)用方法,每個非終結(jié)符表達式只關(guān)心與自己相關(guān)的表達式,每個表達式需要知道最終的結(jié)果,必須通過遞歸方式,無論是面向?qū)ο蟮恼Z言還是面向過程的語言,遞歸都是一個不推薦的方式。由于使用了大量的循環(huán)和遞歸,效率是一個不容忽視的問題。特別是用于解釋一個解析復(fù)雜、冗長的語法時,效率是難以忍受的。
解釋器模式的適用場景 在以下情況下可以使用解釋器模式:
有一個簡單的語法規(guī)則,比如一個sql語句,如果我們需要根據(jù)sql語句進行rm轉(zhuǎn)換,就可以使用解釋器模式來對語句進行解釋。
一些重復(fù)發(fā)生的問題,比如加減乘除四則運算,但是公式每次都不同,有時是a+b-cd,有時是ab+c-d,等等等等個,公式千變?nèi)f化,但是都是由加減乘除四個非終結(jié)符來連接的,這時我們就可以使用解釋器模式。
注意事項 解釋器模式真的是一個比較少用的模式,因為對它的維護實在是太麻煩了,想象一下,一坨一坨的非終結(jié)符解釋器,假如不是事先對文法的規(guī)則了如指掌,或者是文法特別簡單,則很難讀懂它的邏輯。解釋器模式在實際的系統(tǒng)開發(fā)中使用的很少,因為他會引起效率、性能以及維護等問題。