欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

解析Java的設(shè)計(jì)模式編程之解釋器模式的運(yùn)用

 更新時(shí)間:2016年02月17日 11:24:04   作者:卡奴達(dá)摩  
這篇文章主要介紹了解析Java的設(shè)計(jì)模式編程之解釋器模式的運(yùn)用,文中對(duì)解釋器模式的優(yōu)缺點(diǎn)及適用場(chǎng)景作出了分析,需要的朋友可以參考下

定義:給定一種語(yǔ)言,定義他的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來(lái)解釋語(yǔ)言中句子。
類型:行為類模式
類圖:

2016217111905971.jpg (583×309)

解釋器模式是一個(gè)比較少用的模式,本人之前也沒(méi)有用過(guò)這個(gè)模式。下面我們就來(lái)一起看一下解釋器模式。
 
解釋器模式的結(jié)構(gòu)
抽象解釋器:聲明一個(gè)所有具體表達(dá)式都要實(shí)現(xiàn)的抽象接口(或者抽象類),接口中主要是一個(gè)interpret()方法,稱為解釋操作。具體解釋任務(wù)由它的各個(gè)實(shí)現(xiàn)類來(lái)完成,具體的解釋器分別由終結(jié)符解釋器TerminalExpression和非終結(jié)符解釋器NonterminalExpression完成。
終結(jié)符表達(dá)式:實(shí)現(xiàn)與文法中的元素相關(guān)聯(lián)的解釋操作,通常一個(gè)解釋器模式中只有一個(gè)終結(jié)符表達(dá)式,但有多個(gè)實(shí)例,對(duì)應(yīng)不同的終結(jié)符。終結(jié)符一半是文法中的運(yùn)算單元,比如有一個(gè)簡(jiǎn)單的公式R=R1+R2,在里面R1和R2就是終結(jié)符,對(duì)應(yīng)的解析R1和R2的解釋器就是終結(jié)符表達(dá)式。                               
非終結(jié)符表達(dá)式:文法中的每條規(guī)則對(duì)應(yīng)于一個(gè)非終結(jié)符表達(dá)式,非終結(jié)符表達(dá)式一般是文法中的運(yùn)算符或者其他關(guān)鍵字,比如公式R=R1+R2中,+就是非終結(jié)符,解析+的解釋器就是一個(gè)非終結(jié)符表達(dá)式。非終結(jié)符表達(dá)式根據(jù)邏輯的復(fù)雜程度而增加,原則上每個(gè)文法規(guī)則都對(duì)應(yīng)一個(gè)非終結(jié)符表達(dá)式。
環(huán)境角色:這個(gè)角色的任務(wù)一般是用來(lái)存放文法中各個(gè)終結(jié)符所對(duì)應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環(huán)境角色中,很多情況下我們使用Map來(lái)充當(dāng)環(huán)境角色就足夠了。

例子
來(lái)舉一個(gè)加減乘除的例子吧,實(shí)現(xiàn)思路來(lái)自于《java與模式》中的例子。每個(gè)角色的功能按照上面提到的規(guī)范來(lái)實(shí)現(xiàn)。

//上下文(環(huán)境)角色,使用HashMap來(lái)存儲(chǔ)變量對(duì)應(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á)式角色,也可以用接口來(lái)實(shí)現(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對(duì)象 
 
       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; 
 
       } 
 
    } 
 
} 

//測(cè)試程序,計(jì)算 (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); 
 
//運(yùn)算,對(duì)句子的結(jié)構(gòu)由我們自己來(lái)分析,構(gòu)造 
 
       ex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c)); 
 
       System.out.println("運(yùn)算結(jié)果為:"+ex.interpret(con)); 
 
    } 
 
} 

解釋器模式的優(yōu)缺點(diǎn)
        解釋器是一個(gè)簡(jiǎn)單的語(yǔ)法分析工具,它最顯著的優(yōu)點(diǎn)就是擴(kuò)展性,修改語(yǔ)法規(guī)則只需要修改相應(yīng)的非終結(jié)符就可以了,若擴(kuò)展語(yǔ)法,只需要增加非終結(jié)符類就可以了。
        但是,解釋器模式會(huì)引起類的膨脹,每個(gè)語(yǔ)法都需要產(chǎn)生一個(gè)非終結(jié)符表達(dá)式,語(yǔ)法規(guī)則比較復(fù)雜時(shí),就可能產(chǎn)生大量的類文件,為維護(hù)帶來(lái)非常多的麻煩。同時(shí),由于采用遞歸調(diào)用方法,每個(gè)非終結(jié)符表達(dá)式只關(guān)心與自己相關(guān)的表達(dá)式,每個(gè)表達(dá)式需要知道最終的結(jié)果,必須通過(guò)遞歸方式,無(wú)論是面向?qū)ο蟮恼Z(yǔ)言還是面向過(guò)程的語(yǔ)言,遞歸都是一個(gè)不推薦的方式。由于使用了大量的循環(huán)和遞歸,效率是一個(gè)不容忽視的問(wèn)題。特別是用于解釋一個(gè)解析復(fù)雜、冗長(zhǎng)的語(yǔ)法時(shí),效率是難以忍受的。
 
解釋器模式的適用場(chǎng)景
        在以下情況下可以使用解釋器模式:
有一個(gè)簡(jiǎn)單的語(yǔ)法規(guī)則,比如一個(gè)sql語(yǔ)句,如果我們需要根據(jù)sql語(yǔ)句進(jìn)行rm轉(zhuǎn)換,就可以使用解釋器模式來(lái)對(duì)語(yǔ)句進(jìn)行解釋。
一些重復(fù)發(fā)生的問(wèn)題,比如加減乘除四則運(yùn)算,但是公式每次都不同,有時(shí)是a+b-c*d,有時(shí)是a*b+c-d,等等等等個(gè),公式千變?nèi)f化,但是都是由加減乘除四個(gè)非終結(jié)符來(lái)連接的,這時(shí)我們就可以使用解釋器模式。


注意事項(xiàng)
       解釋器模式真的是一個(gè)比較少用的模式,因?yàn)閷?duì)它的維護(hù)實(shí)在是太麻煩了,想象一下,一坨一坨的非終結(jié)符解釋器,假如不是事先對(duì)文法的規(guī)則了如指掌,或者是文法特別簡(jiǎn)單,則很難讀懂它的邏輯。解釋器模式在實(shí)際的系統(tǒng)開(kāi)發(fā)中使用的很少,因?yàn)樗麜?huì)引起效率、性能以及維護(hù)等問(wèn)題。

相關(guān)文章

  • SpringBoot整合redis+lettuce的方法詳解

    SpringBoot整合redis+lettuce的方法詳解

    這篇文章主要介紹了SpringBoot整合redis+lettuce的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Java?Timer與TimerTask類使程序計(jì)時(shí)執(zhí)行

    Java?Timer與TimerTask類使程序計(jì)時(shí)執(zhí)行

    這篇文章主要介紹了Java定時(shí)器中的Timer和TimerTask的原理。Timer主要用于Java線程里指定時(shí)間或周期運(yùn)行任務(wù),它是線程安全的,但不提供實(shí)時(shí)性(real-time)保證。接下來(lái)就跟隨小編一起深入了解Timer和TimerTask吧
    2022-02-02
  • springboot 跨域配置類及跨域請(qǐng)求配置

    springboot 跨域配置類及跨域請(qǐng)求配置

    這篇文章主要介紹了springboot 跨域配置類及跨域請(qǐng)求配置,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • 搭建 springboot selenium 網(wǎng)頁(yè)文件轉(zhuǎn)圖片環(huán)境的詳細(xì)教程

    搭建 springboot selenium 網(wǎng)頁(yè)文件轉(zhuǎn)圖片環(huán)境的詳細(xì)教程

    這篇文章主要介紹了搭建 springboot selenium 網(wǎng)頁(yè)文件轉(zhuǎn)圖片環(huán)境,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 詳解JDBC使用

    詳解JDBC使用

    JDBC(Java Database Connectivity),即Java數(shù)據(jù)庫(kù)連接,是一種用于執(zhí)行SQL語(yǔ)句的Java API,可以為多種關(guān)系數(shù)據(jù)庫(kù)提供同一訪問(wèn),它由一組用Java語(yǔ)言編寫(xiě)的類和接口組成。
    2017-05-05
  • mybatis mapper互相引用resultMap啟動(dòng)出錯(cuò)的解決

    mybatis mapper互相引用resultMap啟動(dòng)出錯(cuò)的解決

    這篇文章主要介紹了mybatis mapper互相引用resultMap啟動(dòng)出錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Javabean簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Javabean簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了Javabean簡(jiǎn)介,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • Java實(shí)例講解多態(tài)數(shù)組的使用

    Java實(shí)例講解多態(tài)數(shù)組的使用

    本文章向大家介紹Java多態(tài)數(shù)組,主要包括Java多態(tài)數(shù)組使用實(shí)例、基本知識(shí)點(diǎn)總結(jié)和需要注意事項(xiàng),具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-05-05
  • java數(shù)據(jù)結(jié)構(gòu)與算法之馬踏棋盤(pán)

    java數(shù)據(jù)結(jié)構(gòu)與算法之馬踏棋盤(pán)

    這篇文章主要為大家詳細(xì)介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之馬踏棋盤(pán),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 關(guān)于Java中的dozer對(duì)象轉(zhuǎn)換問(wèn)題

    關(guān)于Java中的dozer對(duì)象轉(zhuǎn)換問(wèn)題

    Dozer是Java?Bean到Java?Bean映射器,它以遞歸方式將數(shù)據(jù)從一個(gè)對(duì)象復(fù)制到另一個(gè)對(duì)象,這篇文章主要介紹了Java中的dozer對(duì)象轉(zhuǎn)換的操作方法,需要的朋友可以參考下
    2022-08-08

最新評(píng)論