模式的定義
解釋器模式(Pattern Interpreter)是一種按照規定文法進行解析的方案,在現在項目中使用較少。其定義如下:
Given a language,define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
給定一門語言,定義它的文法的一種表示,并定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。
類型
行為類
模式的使用場景
- 重複發生的問題可以使用解釋器模式
- 一個簡單文法需要解釋的場景
注意事項
盡量不要在重要的子產品中使用解釋器子產品,否則維護會是一個很大的問題。
解釋器模式在實際的系統開發中使用得非常少了,因為它會引起效率,性能和維護的問題。一般在大中型的架構型項目能夠找到它的身影,如果你要使用它,可以虛拟一下Expression4J,MESP(Math Expression String Parser),Jep等開源的解釋器工具包,功能都異常強大,而且非常容易使用,效率也還不錯,實作大多數的數學運算完全沒有問題,自己沒有必要從頭開始編寫解釋器。
優點
解釋器是一個簡單文法分析工具,它最顯著的優點就是擴充性,修改文法規則隻要修改相應的非終結符表達式就可以了,若擴充文法,則隻要增加非終結符類就可以。
缺點
-
解釋器模式會引起類膨脹
每個文法都要産生一個非終結符表達式,文法規則比較複雜時,就可能産生大量的類檔案,為維護帶來了非常多的麻煩。
- 解釋器模式采用遞歸調用方法,邏輯複雜,調試不友善
- 由于大量使用循環和遞歸,效率問題要考慮
UML類圖
角色介紹
AbstractExpression—抽象解釋器
具體的解釋任務由各個實作類完成,具體解釋器分别由TerminalExpression和NonterminalExpression完成。
TerminalExpression—-終結符表達式
實作與方法中的元素相關聯的解釋操作,通常一個解釋器模式中隻有一個終結符表達式,但有多個執行個體,對應不同的終結符。
NonterminalExpression—非終結符表達式
文法中的每條規則對應于一個非終結符表達式
Context—環境角色
模式的通用源碼
Expression:
public abstract class Expression {
//每個表達式必須有一個解析任務
public abstract Object interpreter(Context context);
}
抽象表達式是生成文法集合(也叫做文法樹)的關鍵,每個文法集合完成指定文法解析任務,它是通過遞歸調用的方式,最終由最小的文法單元進行解析完成。
TerminalExpression:
public class TerminalExpression extends Expression {
//通常終結符表達式隻有一個,但是有多個對象
@Override
public Object interpreter(Context context) {
// TODO Auto-generated method stub
return null;
}
}
終結符表達式比較簡單,主要是處理場景元素和資料的轉換。
NonterminalExpression:
public class NonterminalExpression extends Expression {
//每個非終結符表達式都會對其他表達式産生依賴
public NonterminalExpression(Expression... expressions) {
// TODO Auto-generated constructor stub
}
@Override
public Object interpreter(Context context) {
// TODO Auto-generated method stub
//進行文法處理
return null;
}
}
每個非終結符表達式都代表一個文法規則,并且每個文法規則都隻關心自己周邊的文法規則的結果,是以這就産生了每個非終結符表達式調用自己周邊的非終結符表達式,然後最終,最小的文法規則就是終結符表達式,終結符表達式的概念就是如此,不能夠再參與比自己更小的方法運算了。
Client:
import java.util.Stack;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Context context = new Context();
//通常定一個文法容器,容納一個具體的表達式,通常ListArray,LinkedList,Stact靠等類型
Stack<Expression> stack = null;
for (;;) {
//進行文法判斷,并産生遞歸調用
}
//産生一個完整的文法樹,由各個具體的文法分析進行解析
Expression expression = stack.pop();
//具體元素進入場景
expression.interpreter(context);
}
}
參考資料
(1).設計模式之禅—第27章 解釋器模式
(2)解釋器模式
https://github.com/simple-android-framework/android_design_patterns_analysis