国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

深入淺出基于Java的解釋器設(shè)計模式

2019-11-18 11:37:12
字體:
供稿:網(wǎng)友
一、引子

  其實沒有什么好的例子引入解釋器模式,因為它描述了如何構(gòu)成一個簡單的語言解釋器,主要應(yīng)用在使用面向?qū)ο笳Z言開發(fā)編譯器中;在實際應(yīng)用中,我們可能很少碰到去構(gòu)造一個語言的文法的情況。

  雖然你幾乎用不到這個模式,但是看一看還是能受到一定的啟發(fā)的。

  二、定義與結(jié)構(gòu)

  解釋器模式的定義如下:定義語言的文法,并且建立一個解釋器來解釋該語言中的句子。它屬于類的行為模式。這里的語言意思是使用規(guī)定格式和語法的代碼。

  在GOF的書中指出:假如一種特定類型的問題發(fā)生的頻率足夠高,那么可能就值得將該問題的各個實例表述為一個簡單語言中的句子。這樣就可以構(gòu)建一個解釋器,該解釋器通過解釋這些句子來解決該問題。而且當(dāng)文法簡單、效率不是要害問題的時候效果最好。

  這也就是解釋器模式應(yīng)用的環(huán)境了。

  讓我們來看看神秘的解釋器模式是由什么來組成的吧。

  1) 抽象表達(dá)式角色:聲明一個抽象的解釋操作,這個接口為所有具體表達(dá)式角色(抽象語法樹中的節(jié)點)都要實現(xiàn)的。

  什么叫做抽象語法樹呢?《java與模式》中給的解釋為:抽象語法樹的每一個節(jié)點都代表一個語句,而在每個節(jié)點上都可以執(zhí)行解釋方法。這個解釋方法的執(zhí)行就代表這個語句被解釋。由于每一個語句都代表這個語句被解釋。由于每一個語句都代表一個常見的問題的實例,因此每一個節(jié)點上的解釋操作都代表對一個問題實例的解答。

  2) 終結(jié)符表達(dá)式角色:具體表達(dá)式。

  a) 實現(xiàn)與文法中的終結(jié)符相關(guān)聯(lián)的解釋操作

  b) 而且句子中的每個終結(jié)符需要該類的一個實例與之對應(yīng)

  3) 非終結(jié)符表達(dá)式角色:具體表達(dá)式。

  a) 文法中的每條規(guī)則R::=R1R2…Rn都需要一個非終結(jié)符表帶式角色

  b) 對于從R1到Rn的每個符號都維護(hù)一個抽象表達(dá)式角色的實例變量

  c) 實現(xiàn)解釋操作,解釋一般要遞歸地調(diào)用表示從R1到Rn的那些對象的解釋操作

  4) 上下文(環(huán)境)角色:包含解釋器之外的一些全局信息。

  5) 客戶角色:

  a) 構(gòu)建(或者被給定)表示該文法定義的語言中的一個特定的句子的抽象語法樹

  b) 調(diào)用解釋操作

  放上張解釋器結(jié)構(gòu)類圖吧,這也是來自于GOF的書中。

深入淺出基于Java的解釋器設(shè)計模式

  對每一個角色都給出了具體的職責(zé),而且在類圖中給出五個角色之間的關(guān)系。這樣實現(xiàn)起來也不是很困難了,下面舉了一個簡單的例子,希望能加深你對解釋器模式的理解。
QQ病毒 騰訊QQ空間代碼專題 PPT教程專題 ADSL應(yīng)用面面俱到 fireworks教程專題 計算機(jī)和網(wǎng)絡(luò)技術(shù)基礎(chǔ)知識 校園網(wǎng)專題 網(wǎng)吧技術(shù)專題

三、舉例

  來舉一個加減乘除的例子吧,實現(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 ;
 }
}

//抽象表達(dá)式角色,也可以用接口來實現(xiàn)

abstract class EXPression
{
 public abstract int interpret(Context con);
}

//終結(jié)符表達(dá)式角色

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é)符表達(dá)式角色

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));
 }
}
  解釋器模式并沒有說明如何創(chuàng)建一個抽象語法樹,因此它的實現(xiàn)可以多種多樣,在上面我們是直接在Test中提供的,當(dāng)然還有更好、更專業(yè)的實現(xiàn)方式。

  對于終結(jié)符,GOF建議采用享元模式來共享它們的拷貝,因為它們要多次重復(fù)出現(xiàn)。但是考慮到享元模式的使用局限性,我建議還是當(dāng)你的系統(tǒng)中終結(jié)符重復(fù)的足夠多的時候再考慮享元模式。

  四、優(yōu)缺點

  解釋器模式提供了一個簡單的方式來執(zhí)行語法,而且輕易修改或者擴(kuò)展語法。一般系統(tǒng)中很多類使用相似的語法,可以使用一個解釋器來代替為每一個規(guī)則實現(xiàn)一個解釋器。而且在解釋器中不同的規(guī)則是由不同的類來實現(xiàn)的,這樣使得添加一個新的語法規(guī)則變得簡單。

  但是解釋器模式對于復(fù)雜文法難以維護(hù)。可以想象一下,每一個規(guī)則要對應(yīng)一個處理類,而且這些類還要遞歸調(diào)用抽象表達(dá)式角色,多如亂麻的類交織在一起是多么恐怖的一件事啊!

  五、總結(jié)

  這樣對解釋器模式應(yīng)該有了些大體的熟悉了吧,由于這個模式使用的案例匱乏,所以本文大部分觀點直接來自于GOF的原著。只是實例代碼是親自實現(xiàn)并調(diào)試通過的。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 山丹县| 建始县| 八宿县| 中江县| 白朗县| 宜宾县| 竹溪县| 玉林市| 额尔古纳市| 湾仔区| 玉环县| 万州区| 历史| 兴和县| 祁门县| 蛟河市| 桃园市| 武穴市| 惠东县| 松原市| 宁远县| 林周县| 宁陵县| 凤山市| 玉龙| 建平县| 新乡县| 庆阳市| 屯留县| 达州市| 廊坊市| 辉县市| 四平市| 永寿县| 琼海市| 巴彦县| 胶州市| 永嘉县| 安化县| 安化县| 嘉荫县|