interpreter(解釋器模式)

来源:http://www.cnblogs.com/yzjT-mac/archive/2016/12/30/6237820.html
-Advertisement-
Play Games

由於解釋器模式基本不用,我就直接轉載網上的了,大家看看漲漲姿勢http://blog.csdn.net/ylchou/article/details/7594135 一、引子 其實沒有什麼好的例子引入解釋器模式,因為它描述瞭如何構成一個簡單的語言解釋器,主要應用在使用面向對象語言開發編譯器中;在實際 ...


一、引子
其實沒有什麼好的例子引入解釋器模式,因為它描述瞭如何構成一個簡單的語言解釋器,主要應用在使用面向對象語言開發編譯器中;在實際應用中,我們可能很少碰到去構造一個語言的文法的情況。
       雖然你幾乎用不到這個模式,但是看一看還是能受到一定的啟發的。
 
二、定義與結構
解釋器模式的定義如下:定義語言的文法,並且建立一個解釋器來解釋該語言中的句子。它屬於類的行為模式。這裡的語言意思是使用規定格式和語法的代碼。
       在GOF的書中指出:如果一種特定類型的問題發生的頻率足夠高,那麼可能就值得將該問題的各個實例表述為一個簡單語言中的句子。這樣就可以構建一個解釋器,該解釋器通過解釋這些句子來解決該問題。而且當文法簡單、效率不是關鍵問題的時候效果最好。
       呵呵,這也就是解釋器模式應用的環境了。
       讓我們來看看神秘的解釋器模式是由什麼來組成的吧。
1)        抽象表達式角色:聲明一個抽象的解釋操作,這個介面為所有具體表達式角色(抽象語法樹中的節點)都要實現的。
什麼叫做抽象語法樹呢?《Java與模式》中給的解釋為:抽象語法樹的每一個節點都代表一個語句,而在每個節點上都可以執行解釋方法。這個解釋方法的執行就代表這個語句被解釋。由於每一個語句都代表這個語句被解釋。由於每一個語句都代表一個常見的問題的實例,因此每一個節點上的解釋操作都代表對一個問題實例的解答。
2)        終結符表達式角色:具體表達式。
a)        實現與文法中的終結符相關聯的解釋操作
b)        而且句子中的每個終結符需要該類的一個實例與之對應
3)        非終結符表達式角色:具體表達式。
a)        文法中的每條規則R::=R1R2…Rn都需要一個非終結符錶帶式角色
b)        對於從R1到Rn的每個符號都維護一個抽象表達式角色的實例變數
c)        實現解釋操作,解釋一般要遞歸地調用表示從R1到Rn的那些對象的解釋操作
4)        上下文(環境)角色:包含解釋器之外的一些全局信息。
5)        客戶角色:
a)        構建(或者被給定)表示該文法定義的語言中的一個特定的句子的抽象語法樹
b)        調用解釋操作
 
放上張解釋器結構類圖吧,這也是來自於GOF的書中。



呵呵,對每一個角色都給出了詳細的職責,而且在類圖中給出五個角色之間的關係。這樣實現起來也不是很困難了,下麵舉了一個簡單的例子,希望能加深你對解釋器模式的理解。
 
三、舉例
來舉一個加減乘除的例子吧,實現思路來自於《java與模式》中的例子。每個角色的功能按照上面提到的規範來實現。
 
[java] view plain copy
//上下文(環境)角色,使用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 ;  
  
       }  
  
}  

[java] view plain copy
//抽象表達式角色,也可以用介面來實現  
  
abstract class Expression  
  
{  
  
       public abstract int interpret(Context con);  
  
}  

[java] view plain copy
//終結符表達式角色  
  
class Constant extends Expression  
  
{  
  
       private int i ;  
  
       public Constant(int i)  
  
       {  
  
              this.i = i;  
  
       }  
  
       public int interpret(Context con)  
  
       {  
  
              return i ;  
  
       }  
  
}  

[java] view plain copy
class Variable extends Expression  
  
{  
  
       public int interpret(Context con)  
  
       {  
  
              //this為調用interpret方法的Variable對象  
  
              return con.LookupValue(this);  
  
       }  
  
}  

[java] view plain copy
//非終結符表達式角色  
  
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);  
  
       }  
  
}  

[java] view plain copy
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);  
  
       }  
  
}  

[java] view plain copy
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);  
  
       }  
  
}  

[java] view plain copy
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;  
  
              }  
  
       }  
  
}  

[java] view plain copy
//測試程式,計算 (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));  
  
       }  
  
}  

解釋器模式並沒有說明如何創建一個抽象語法樹,因此它的實現可以多種多樣,在上面我們是直接在Test中提供的,當然還有更好、更專業的實現方式。
對於終結符,GOF建議採用享元模式來共用它們的拷貝,因為它們要多次重覆出現。但是考慮到享元模式的使用局限性,我建議還是當你的系統中終結符重覆的足夠多的時候再考慮享元模式(關於享元模式,請參考我的《深入淺出享元模式》)。
 
四、優缺點
解釋器模式提供了一個簡單的方式來執行語法,而且容易修改或者擴展語法。一般系統中很多類使用相似的語法,可以使用一個解釋器來代替為每一個規則實現一個解釋器。而且在解釋器中不同的規則是由不同的類來實現的,這樣使得添加一個新的語法規則變得簡單。
但是解釋器模式對於複雜文法難以維護。可以想象一下,每一個規則要對應一個處理類,而且這些類還要遞歸調用抽象表達式角色,多如亂麻的類交織在一起是多麼恐怖的一件事啊!
 
五、總結
這樣對解釋器模式應該有了些大體的認識了吧,由於這個模式使用的案例匱乏,所以本文大部分觀點直接來自於GOF的原著。只是實例代碼是親自實現並調試通過的。

由於解釋器模式基本不用,我就直接轉載網上的了,大家看看漲漲姿勢http://blog.csdn.net/ylchou/article/details/7594135

一、引子

其實沒有什麼好的例子引入解釋器模式,因為它描述瞭如何構成一個簡單的語言解釋器,主要應用在使用面向對象語言開發編譯器中;在實際應用中,我們可能很少碰到去構造一個語言的文法的情況。

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

 

二、定義與結構

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

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

       呵呵,這也就是解釋器模式應用的環境了。

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

1)        抽象表達式角色:聲明一個抽象的解釋操作,這個介面為所有具體表達式角色(抽象語法樹中的節點)都要實現的。

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

2)        終結符表達式角色:具體表達式。

a)        實現與文法中的終結符相關聯的解釋操作

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

3)        非終結符表達式角色:具體表達式。

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

b)        對於從R1到Rn的每個符號都維護一個抽象表達式角色的實例變數

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

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

5)        客戶角色:

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

b)        調用解釋操作

 

放上張解釋器結構類圖吧,這也是來自於GOF的書中。



呵呵,對每一個角色都給出了詳細的職責,而且在類圖中給出五個角色之間的關係。這樣實現起來也不是很困難了,下麵舉了一個簡單的例子,希望能加深你對解釋器模式的理解。

 

三、舉例

來舉一個加減乘除的例子吧,實現思路來自於《java與模式》中的例子。每個角色的功能按照上面提到的規範來實現。

 

 

[java] view plain copy  
  1. //上下文(環境)角色,使用HashMap來存儲變數對應的數值  
  2.   
  3. class Context  
  4.   
  5. {  
  6.   
  7.        private Map valueMap = new HashMap();  
  8.   
  9.        public void addValue(Variable x , int y)  
  10.   
  11.        {  
  12.   
  13.               Integer yi = new Integer(y);  
  14.   
  15.               valueMap.put(x , yi);  
  16.   
  17.        }  
  18.   
  19.        public int LookupValue(Variable x)  
  20.   
  21.        {  
  22.   
  23.               int i = ((Integer)valueMap.get(x)).intValue();  
  24.   
  25.               return i ;  
  26.   
  27.        }  
  28.   
  29. }  

 

 

 

[java] view plain copy  
  1. //抽象表達式角色,也可以用介面來實現  
  2.   
  3. abstract class Expression  
  4.   
  5. {  
  6.   
  7.        public abstract int interpret(Context con);  
  8.   
  9. }  

 

 

 

[java] view plain copy  
  1. //終結符表達式角色  
  2.   
  3. class Constant extends Expression  
  4.   
  5. {  
  6.   
  7.        private int i ;  
  8.   
  9.        public Constant(int i)  
  10.   
  11.        {  
  12.   
  13.               this.i = i;  
  14.   
  15.        }  
  16.   
  17.        public int interpret(Context con)  
  18.   
  19.        {  
  20.   
  21.               return i ;  
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 題目大意: B進位數,每個數字i(i=0,1,...,B-1)有a[i]個。你要用這些數字組成一個最大的B進位數X(不能有前導零,不需要 用完所有數字),使得X是B-1的倍數。q次詢問,每次詢問X在B進位下的第k位數字是什麼(最低位是第0位)。 思路:由於如下定理: a*Bk≡a( mod (B-1 ...
  • 當子類繼承父類的時候,若父類沒有定義帶參的構造方法,則子類可以繼承父類的預設構造方法 當父類中定義了帶參的構造方法,子類必須顯式的調用父類的構造方法 若此時,子類還想調用父類的預設構造方法,必須在父類中明確聲明預設的構造方法 ...
  • set 的 remove() 和 discard() 方法介紹。 函數/方法名 for example: 以下運行代碼會報錯,原因在於 第9行 remove()中的‘l’在集合中不存在 而 discard()方法不會報錯。 正確的代碼如下: 運行結果如下: ...
  • Peter wants to generate some prime numbers for his cryptosystem. Help him! Your task is to generate all prime numbers between two given numbers! Input ...
  • 在上一集的討論里我們介紹並實現了強類型返回結果行。使用強類型主要的目的是當我們把後端資料庫SQL批次操作搬到記憶體里轉變成數據流式按行操作時能更方便、準確、高效地選定數據欄位。在上集討論示範里我們用集合的foreach方式模擬了一個最簡單的數據流,並把從資料庫里批次讀取的數據集轉換成一串連續的數據行來 ...
  • 雖然公司自己的網站和給客戶開發的項目中都涉及到了微信開發,自己也寫了關於微信開發的兩篇文章,但感覺自己對微信開發中的一些概念還是容易混淆,今天瀏覽了下微信公眾平臺、微信開放平臺的後臺和相關文檔,算是弄清楚了下麵這些東西,至於其他還沒弄清楚的,以後想到了再說。 1,微信公眾平臺(https://mp. ...
  • 一、前言 在上一篇博文中,我們的爬蟲面臨著一個問題,在爬取Unsplash網站的時候,由於網站是下拉刷新,並沒有分頁。所以不能夠通過頁碼獲取頁面的url來分別發送網路請求。我也嘗試了其他方式,比如下拉的時候監控http請求,看看請求是否有規律可以模擬。後來發現請求並沒有規律,也就是不能夠模擬http ...
  • 一、Scrapy簡介 Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程式中。 Scrapy基於事件驅動網路框架 Twisted 編寫。因此,Scrapy基於併發性考慮由非阻塞(即非同步)的實現。 組件 Scrapy Eng ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...