解析Java的設計形式編程之說明器形式的應用。本站提示廣大學習愛好者:(解析Java的設計形式編程之說明器形式的應用)文章只能為提供參考,不一定能成為您想要的結果。以下是解析Java的設計形式編程之說明器形式的應用正文
界說:給定一種說話,界說他的文法的一種表現,並界說一個說明器,該說明器應用該表現來說明說話中句子。
類型:行動類形式
類圖:
說明器形式是一個比擬罕用的形式,自己之前也沒有效過這個形式。上面我們就來一路看一下說明器形式。
說明器形式的構造
籠統說明器:聲明一個一切詳細表達式都要完成的籠統接口(或許籠統類),接口中重要是一個interpret()辦法,稱為說明操作。詳細說明義務由它的各個完成類來完成,詳細的說明器分離由終結符說明器TerminalExpression和非終結符說明器NonterminalExpression完成。
終結符表達式:完成與文法中的元素相干聯的說明操作,平日一個說明器形式中只要一個終結符表達式,但有多個實例,對應分歧的終結符。終結符一半是文法中的運算單位,好比有一個簡略的公式R=R1+R2,在外面R1和R2就是終結符,對應的解析R1和R2的說明器就是終結符表達式。
非終結符表達式:文法中的每條規矩對應於一個非終結符表達式,非終結符表達式普通是文法中的運算符或許其他症結字,好比公式R=R1+R2中,+就長短終結符,解析+的說明器就是一個非終結符表達式。非終結符表達式依據邏輯的龐雜水平而增長,准繩上每一個文律例則都對應一個非終結符表達式。
情況腳色:這個腳色的義務普通是用來寄存文法中各個終結符所對應的詳細值,好比R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息須要寄存到情況腳色中,許多情形下我們應用Map來充任情況腳色就足夠了。
例子
來舉一個加減乘除的例子吧,完成思緒來自於《java與形式》中的例子。每一個腳色的功效依照下面提到的標准來完成。
//高低文(情況)腳色,應用HashMap來存儲變量對應的數值 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 ; } } //籠統表達式腳色,也能夠用接口來完成 abstract class Expression { public abstract int interpret(Context con); } //終結符表達式腳色 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為挪用interpret辦法的Variable對象 return con.LookupValue(this); } } //非終結符表達式腳色 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("被除數為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(); //設置變量、常量 Variable a = new Variable(); Variable b = new Variable(); Constant c = new Constant(2); //為變量賦值 con.addValue(a , 5); con.addValue(b , 7); //運算,對句子的構造由我們本身來剖析,結構 ex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c)); System.out.println("運算成果為:"+ex.interpret(con)); } }
說明器形式的優缺陷
說明器是一個簡略的語法剖析對象,它最明顯的長處就是擴大性,修正語律例則只須要修正響應的非終結符便可以了,若擴大語法,只須要增長非終結符類便可以了。
然則,說明器形式會惹起類的收縮,每一個語法都須要發生一個非終結符表達式,語律例則比擬龐雜時,便可能發生年夜量的類文件,為保護帶來異常多的費事。同時,因為采取遞歸挪用辦法,每一個非終結符表達式只關懷與本身相干的表達式,每一個表達式須要曉得終究的成果,必需經由過程遞歸方法,不管是面向對象的說話照樣面向進程的說話,遞歸都是一個不推舉的方法。因為應用了年夜量的輪回和遞歸,效力是一個不容疏忽的成績。特殊是用於說明一個解析龐雜、冗雜的語法時,效力是難以忍耐的。
說明器形式的實用場景
在以下情形下可使用說明器形式:
有一個簡略的語律例則,好比一個sql語句,假如我們須要依據sql語句停止rm轉換,便可以應用說明器形式來對語句停止說明。
一些反復產生的成績,好比加減乘除四則運算,然則公式每次都分歧,有時是a+b-c*d,有時是a*b+c-d,等等等等個,公式千變萬化,然則都是由加減乘除四個非終結符來銜接的,這時候我們便可以應用說明器形式。
留意事項
說明器形式真的是一個比擬罕用的形式,由於對它的保護其實是太費事了,想象一下,一坨一坨的非終結符說明器,假設不是事前對文法的規矩管窺蠡測,或許是文法特殊簡略,則很難讀懂它的邏輯。說明器形式在現實的體系開辟中應用的很少,由於他會惹起效力、機能和保護等成績。