解析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,等等等等個,公式千變萬化,然則都是由加減乘除四個非終結符來銜接的,這時候我們便可以應用說明器形式。
留意事項
說明器形式真的是一個比擬罕用的形式,由於對它的保護其實是太費事了,想象一下,一坨一坨的非終結符說明器,假設不是事前對文法的規矩管窺蠡測,或許是文法特殊簡略,則很難讀懂它的邏輯。說明器形式在現實的體系開辟中應用的很少,由於他會惹起效力、機能和保護等成績。