23種設(shè)計(jì)模式(15)java解釋器模式
23種設(shè)計(jì)模式第十五篇:java解釋器模式
定義:給定一種語言,定義他的文法的一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來解釋語言中句子。
類型:行為類模式
類圖:
解釋器模式是一個(gè)比較少用的模式,本人之前也沒有用過這個(gè)模式。下面我們就來一起看一下解釋器模式。
解釋器模式的結(jié)構(gòu)
抽象解釋器:聲明一個(gè)所有具體表達(dá)式都要實(shí)現(xiàn)的抽象接口(或者抽象類),接口中主要是一個(gè)interpret()方法,稱為解釋操作。具體解釋任務(wù)由它的各個(gè)實(shí)現(xiàn)類來完成,具體的解釋器分別由終結(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è)簡單的公式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ù)一般是用來存放文法中各個(gè)終結(jié)符所對(duì)應(yīng)的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些信息需要存放到環(huán)境角色中,很多情況下我們使用Map來充當(dāng)環(huán)境角色就足夠了。
代碼實(shí)現(xiàn)
class Context {} abstract class Expression { public abstract Object interpreter(Context ctx); } class TerminalExpression extends Expression { public Object interpreter(Context ctx){ return null; } } class NonterminalExpression extends Expression { public NonterminalExpression(Expression...expressions){ } public Object interpreter(Context ctx){ return null; } } public class Client { public static void main(String[] args){ String expression = ""; char[] charArray = expression.toCharArray(); Context ctx = new Context(); Stack<Expression> stack = new Stack<Expression>(); for(int i=0;i<charArray.length;i++){ //進(jìn)行語法判斷,遞歸調(diào)用 } Expression exp = stack.pop(); exp.interpreter(ctx); } }
文法遞歸的代碼部分需要根據(jù)具體的情況來實(shí)現(xiàn),因此在代碼中沒有體現(xiàn)。抽象表達(dá)式是生成語法集合的關(guān)鍵,每個(gè)非終結(jié)符表達(dá)式解釋一個(gè)最小的語法單元,然后通過遞歸的方式將這些語法單元組合成完整的文法,這就是解釋器模式。
解釋器模式的優(yōu)缺點(diǎn)
解釋器是一個(gè)簡單的語法分析工具,它最顯著的優(yōu)點(diǎn)就是擴(kuò)展性,修改語法規(guī)則只需要修改相應(yīng)的非終結(jié)符就可以了,若擴(kuò)展語法,只需要增加非終結(jié)符類就可以了。
但是,解釋器模式會(huì)引起類的膨脹,每個(gè)語法都需要產(chǎn)生一個(gè)非終結(jié)符表達(dá)式,語法規(guī)則比較復(fù)雜時(shí),就可能產(chǎn)生大量的類文件,為維護(hù)帶來非常多的麻煩。同時(shí),由于采用遞歸調(diào)用方法,每個(gè)非終結(jié)符表達(dá)式只關(guān)心與自己相關(guān)的表達(dá)式,每個(gè)表達(dá)式需要知道最終的結(jié)果,必須通過遞歸方式,無論是面向?qū)ο蟮恼Z言還是面向過程的語言,遞歸都是一個(gè)不推薦的方式。由于使用了大量的循環(huán)和遞歸,效率是一個(gè)不容忽視的問題。特別是用于解釋一個(gè)解析復(fù)雜、冗長的語法時(shí),效率是難以忍受的。
解釋器模式的適用場景
在以下情況下可以使用解釋器模式:
有一個(gè)簡單的語法規(guī)則,比如一個(gè)sql語句,如果我們需要根據(jù)sql語句進(jìn)行rm轉(zhuǎn)換,就可以使用解釋器模式來對(duì)語句進(jìn)行解釋。
一些重復(fù)發(fā)生的問題,比如加減乘除四則運(yùn)算,但是公式每次都不同,有時(shí)是a+b-c*d,有時(shí)是a*b+c-d,等等等等個(gè),公式千變?nèi)f化,但是都是由加減乘除四個(gè)非終結(jié)符來連接的,這時(shí)我們就可以使用解釋器模式。
注意事項(xiàng)
解釋器模式真的是一個(gè)比較少用的模式,因?yàn)閷?duì)它的維護(hù)實(shí)在是太麻煩了,想象一下,一坨一坨的非終結(jié)符解釋器,假如不是事先對(duì)文法的規(guī)則了如指掌,或者是文法特別簡單,則很難讀懂它的邏輯。解釋器模式在實(shí)際的系統(tǒng)開發(fā)中使用的很少,因?yàn)樗麜?huì)引起效率、性能以及維護(hù)等問題。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解析Apache Dubbo的SPI實(shí)現(xiàn)機(jī)制
SPI全稱為Service Provider Interface,對(duì)應(yīng)中文為服務(wù)發(fā)現(xiàn)機(jī)制。SPI類似一種可插拔機(jī)制,首先需要定義一個(gè)接口或一個(gè)約定,然后不同的場景可以對(duì)其進(jìn)行實(shí)現(xiàn),調(diào)用方在使用的時(shí)候無需過多關(guān)注具體的實(shí)現(xiàn)細(xì)節(jié)2021-06-06分析Java并發(fā)編程之信號(hào)量Semaphore
Semaphore一般譯作信號(hào)量,它也是一種線程同步工具,主要用于多個(gè)線程對(duì)共享資源進(jìn)行并行操作的一種工具類。它代表了一種許可的概念,是否允許多線程對(duì)同一資源進(jìn)行操作的許可,使用Semaphore可以控制并發(fā)訪問資源的線程個(gè)數(shù)2021-06-06java判斷l(xiāng)ist不為空的實(shí)現(xiàn),和限制條數(shù)不要在一起寫
這篇文章主要介紹了java判斷l(xiāng)ist不為空的實(shí)現(xiàn),和限制條數(shù)不要在一起寫。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-01-01Java將json對(duì)象轉(zhuǎn)換為map鍵值對(duì)案例詳解
這篇文章主要介紹了Java將json對(duì)象轉(zhuǎn)換為map鍵值對(duì)案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09java編寫創(chuàng)建數(shù)據(jù)庫和表的程序
這篇文章主要為大家詳細(xì)介紹了java編寫創(chuàng)建數(shù)據(jù)庫和表的程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Java方法重寫_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
在Java和其他一些高級(jí)面向?qū)ο蟮木幊陶Z言中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時(shí)子類并不想原封不動(dòng)地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋,下文給大家介紹java方法重寫及重寫規(guī)則,一起學(xué)習(xí)吧2017-04-04Java Spring的數(shù)據(jù)庫開發(fā)詳解
這篇文章主要介紹了Spring的數(shù)據(jù)庫開發(fā),主要圍繞SpringJDBC和Spring Jdbc Template兩個(gè)技術(shù)來講解,文中有詳細(xì)的代碼示例,需要的小伙伴可以參考一下2023-04-04springboot新建項(xiàng)目jdk只有17/21,無法選中1.8解決辦法
最近博主也有創(chuàng)建springboot項(xiàng)目,發(fā)現(xiàn)了IntelliJ IDEA在通過Spring Initilizer初始化項(xiàng)目的時(shí)候已經(jīng)沒有java8版本的選項(xiàng)了,這里給大家總結(jié)下,這篇文章主要給大家介紹了springboot新建項(xiàng)目jdk只有17/21,無法選中1.8的解決辦法,需要的朋友可以參考下2023-12-12SpringMVC多個(gè)模塊404報(bào)錯(cuò)問題及解決
這篇文章主要介紹了SpringMVC多個(gè)模塊404報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09