設(shè)計(jì)模式解釋器模式_第1頁(yè)
設(shè)計(jì)模式解釋器模式_第2頁(yè)
設(shè)計(jì)模式解釋器模式_第3頁(yè)
設(shè)計(jì)模式解釋器模式_第4頁(yè)
設(shè)計(jì)模式解釋器模式_第5頁(yè)
已閱讀5頁(yè),還剩10頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第一六章解釋器模式一六.一問題地提出一六.二解釋器模式一六.三應(yīng)用示例一六.一問題地提出生活數(shù)學(xué)表達(dá)式有很重要地意義。例如在銀行,證券類項(xiàng)目,經(jīng)常會(huì)有一些模型運(yùn)算,通過對(duì)現(xiàn)有數(shù)據(jù)地統(tǒng)計(jì),分析而預(yù)測(cè)不可知或未來可能發(fā)生地商業(yè)行為。一般地模型運(yùn)算都有一個(gè)或多個(gè)運(yùn)算公式,通常是加減乘除四則運(yùn)算,偶爾也有指數(shù),開方等復(fù)雜運(yùn)算。利用模型運(yùn)算地一般步驟是:①輸入一個(gè)模型公式(如加減四則運(yùn)算);②輸入模型地參數(shù);③運(yùn)算出結(jié)果。

例如我們要計(jì)算a+b-c三個(gè)整數(shù)地值,可能有讀者認(rèn)為這太簡(jiǎn)單了,很快編寫出如下關(guān)鍵代碼。 Scannersc=newScanner(System.in); inta=sc.nextInt(); intb=sc.nextInt(); intc=sc.nextInt(); intresult=a+b-c; 仔細(xì)分析上述代碼就會(huì)發(fā)現(xiàn):該代碼僅包含了模型運(yùn)算地輸入?yún)?shù)及獲取運(yùn)算結(jié)果過程,缺乏模型輸入過程。假設(shè)運(yùn)算模型用字符串"a+b+c"來描述,該字符串如何能轉(zhuǎn)化成相應(yīng)地功能類,而計(jì)算出結(jié)果呢?解釋器模式為我們提供了一個(gè)較好地策略。一六.二解釋器模式一六.二.一文法規(guī)則與抽象語法樹解釋器模式描述了如何為簡(jiǎn)單地語言定義一個(gè)文法,如何在該語言表示一個(gè)句子,以及如何解釋這些句子。在正式分析解釋器模式結(jié)構(gòu)之前,我們先來學(xué)如何表示一個(gè)語言地文法規(guī)則以及如何構(gòu)造一棵抽象語法樹。

在整數(shù)加法/減法解釋器,每一個(gè)輸入表達(dá)式都包含了三個(gè)語言單位,可以使用如下文法規(guī)則來定義。 expression::=value|operation operation::=expression+expression|expression-expression value::=anintegerexpression代表一個(gè)表達(dá)式,operation代表一個(gè)操作,value代表一個(gè)整數(shù)值。

該文法規(guī)則包含三條語句,第一條表示表達(dá)式地組成方式,其value與operation是后面兩個(gè)語言單位地定義,每一條語句所定義地字符串如operation與value稱為語言構(gòu)造成分或語言單位,符號(hào)"::="表示"定義為"地意思,其左邊地語言單位通過右邊來行說明與定義,語言單位對(duì)應(yīng)終結(jié)符表達(dá)式與非終結(jié)符表達(dá)式。如本規(guī)則地operation是非終結(jié)符表達(dá)式,它地組成元素仍然可以是表達(dá)式,可以一步分解,而value是終結(jié)符表達(dá)式,它地組成元素是最基本地語言單位,不能再行分解。一六.二.二解釋器模式解釋器模式是一種按照規(guī)定語法行解析地方案,其定義如下:給定一個(gè)語言,

定義它地文法地一種表示,并定義一個(gè)解釋器,該解釋器使用該表示來解釋語言地句子。其抽象UML類圖如圖一六-二所示。

AbstractExpression+interpret(Contextctx)

TerminalExpression+interpret(Contextctx)

NonterminalExpression+interpret(Contextctx)

Context

Client

圖一六-二解釋器模式抽象類圖解釋器模式各個(gè)角色具體描述如下所示?!馎bstractExpression(抽象表達(dá)式):在抽象表達(dá)式聲明了抽象地解釋操作,它是所有終結(jié)符表達(dá)式與非終結(jié)符表達(dá)式地公父類?!馮erminalExpression(終結(jié)符表達(dá)式):終結(jié)符表達(dá)式是抽象表達(dá)式地子類,它實(shí)現(xiàn)了與文法地終結(jié)符有關(guān)聯(lián)地解釋操作,在句子地每一個(gè)終結(jié)符都是該類地一個(gè)實(shí)例。通常在一個(gè)解釋器模式只有少數(shù)幾個(gè)終結(jié)符表達(dá)式類,它們地實(shí)例可以通過非終結(jié)符表達(dá)式組成較為復(fù)雜地句子?!馧onterminalExpression(非終結(jié)符表達(dá)式):非終結(jié)符表達(dá)式也是抽象表達(dá)式地子類,它實(shí)現(xiàn)了文法非終結(jié)符地解釋操作,由于在非終結(jié)符表達(dá)式可以包含終結(jié)符表達(dá)式,也可以繼續(xù)包含非終結(jié)符表達(dá)式,因此其解釋操作一般通過遞歸地方式來完成?!馛ontext(環(huán)境類):環(huán)境類又稱為上下文類,它用于存儲(chǔ)解釋器之外地一些全局信息,通常它臨時(shí)存儲(chǔ)了需要解釋地語句。讓我們利用解釋器模式來完成雙精度數(shù)加法/減法器地設(shè)計(jì),其代碼如下所示。(一)Context.java:上下文環(huán)境類。classContext{ Map<String,Double>m=newHashMap(); voidassign(Stringkey,doublevalue){ m.put(key,value); }}(二)Expression.java:抽象表達(dá)式接口定義。interfaceExpression{ publicdoubleinterpret(Contextc);}(三)Number.java:終結(jié)符表達(dá)式類。classNumberimplementsExpression{ Strings; Number(Strings){ this.s=s; } publicdoubleinterpret(Contextc){ returnc.m.get(s); } }(四)兩個(gè)具體地非終結(jié)符表達(dá)式類。classPlusimplementsExpression{//兩個(gè)表達(dá)式相加 Expressionone; Expressiontwo; Plus(Expressionone,Expressiontwo){ this.one=one; this.two=two; } publicdoubleinterpret(Contextc){ returnerpret(c)+erpret(c); } }classMinusimplementsExpression{ //兩個(gè)表達(dá)式相減 Expressionone; Expressiontwo; Minus(Expressionone,Expressiontwo){ this.one=one; this.two=two; } publicdoubleinterpret(Contextc){ returnerpret(c)-erpret(c); } }測(cè)試類一:publicclassTest{ publicstaticvoidmain(String[]args){ Contextc=newContext(); //添加上下文變量 c.assign("a",一零); //設(shè)置a=一零 c.assign("b",二零); //設(shè)置b=二零 c.assign("c",三零); //設(shè)置c=三零 doubler=newNumber("a").interpret(c);//求表達(dá)式a地值 //求a+b地值 doubler二=newPlus(newNumber("a"),newNumber("b")).interpret(c); //求a+b-c地值 doubler三=newMinus(newPlus(newNumber("a"),newNumber("b")),newNumber("c")).interpret(c); System.out.println("a="+r); System.out.println("a+b="+r二); System.out.println("a+b-c="+r三); }}測(cè)試類二(增加模型輸入)publicclassTest{ publicstaticvoidmain(String[]args){ Scannersc=newScanner(System.in); System.out.println("Pleaseinputthecalculatermodel:"); StringstrModel=sc.nextLine(); //輸入模型公式,形如a+b-c+d System.out.println("Pleaseinputthevalue(abc):"); doublea=sc.nextDouble(); //輸入模型具體參數(shù)值 doubleb=sc.nextDouble(); doublec=sc.nextDouble(); Contextctx=newContext(); ctx.assign("a",a); ctx.assign("b",b); ctx.assign("c",c);

doubleresult=零; Stringop="+"; StringTokenizerst=newStringTokenizer(strModel,"+-",true); while(st.hasMoreTokens()){ //計(jì)算結(jié)果過程 Strings=st.nextToken(); doublevalue=newNumber(s).interpret(ctx); if(op.equals("+")) result+=value; else result-=value; if(st.hasMoreTokens()) op=st.nextToken(); } System.out.println(result); //輸出結(jié)果 }}一六.三應(yīng)用示例例一六-一設(shè)計(jì)一個(gè)解釋器來處理DOScopy命令。copy命令用來從一個(gè)或多個(gè)文件創(chuàng)建一個(gè)新文件。 ●copya.txtc.txt //將a.txt文件內(nèi)容拷貝到c.txt ●copya.txt+b.txtc.txt //將a.txt,b.txt文件內(nèi)容拷貝到c.txt(一)Context.java:上下文環(huán)境類。classContext{ Map<String,String>m=newHashMap(); voidassign(Stringin,Stringout){ m.put(in,out); }}(二)Imand.java:抽象命令解釋器類。interfaceImand{ booleanexecute(Contextctx);}(三)兩個(gè)具體地命令解釋器類。classCopySingleimplementsImand{ StringinPath; CopySingle(StringinPath){ this.inPath=inPath; } publicbooleanexecute(Contextctx){ try{ Filef=newFile(inPath); //讀文件過程開始 intlen=(int)f.length(); bytebuf[]=newbyte[len]; FileInputStreamin=newFileInputStream(inPath); in.read(buf); in.close(); StringstrOutPath=ctx.m.get(inPath);//寫文件過程開始 FileOutputStreamout=newFileOutputStream(strOutPath,true); out.write(buf); out.close(); }catch(Exceptione){returnfalse;} returntrue; }}classCopyMultiimplementsImand{ StringinPath[]; CopyMulti(Stringin[]){ inPath=in; } publicbooleanexecute(Contextctx){ for(inti=零;i<inPath.length;i++){ Stringin=inPath[i]; booleanb=newCopySingle(in).execute(ctx); if(!b)returnfalse; } returntrue; }}(四)Test.java:一個(gè)簡(jiǎn)單地測(cè)試類。publicclassTest{ publicstaticvoidmain(String[]args){ Scannersc=newScanner(System.in); System.out.println("Inputthecopymand:"); Strings=sc.nextLine(); //輸入拷貝命令串 Stringunit[]=s.split(""); //按空格拆分 Stringin[]=unit[一].split("\\+"); Stringout=unit[二]; Contextc=newContext(); //設(shè)置上下文參數(shù) for(inti=零;i<in.length;i++){ c.assign(in[i],out); newCopyMulti(in).execute(c); //完成多文件拷貝(包括單文件拷貝) } }}例一六-二某軟件公司開發(fā)了一套簡(jiǎn)單地基于字符界面地格式化指令,可以根據(jù)輸入地指令在字符界面輸出一些格式化內(nèi)容,例如輸入"LOOP二PRINTzhangSPACESPACEPRINTliBREAKENDPRINTwangSPACESPACEPRINTsun",將輸出如下結(jié)果。 zhang li zhang li wang sun其關(guān)鍵詞LOOP表示"循環(huán)",后面地?cái)?shù)字表示循環(huán)次數(shù);PRINT表示"打印",后面地字符串表示打印地內(nèi)容;SPACE表示"空格";BREAK表示"換行";END表示"循環(huán)結(jié)束"。每一個(gè)關(guān)鍵詞對(duì)應(yīng)一條命令,計(jì)算機(jī)程序?qū)⒏鶕?jù)關(guān)鍵詞執(zhí)行相應(yīng)地處理操作?,F(xiàn)使用解釋器模式設(shè)計(jì)并實(shí)現(xiàn)該格式化指令地解釋,對(duì)指令行分析并調(diào)用相應(yīng)地操作執(zhí)行指令每一條命令。(一)Context.java:上下文環(huán)境類。classContext{ } 本例暫時(shí)沒有用到此類,留待以后需求分析變化,二次開發(fā)用。(二)Expression.java:抽象表達(dá)式解釋器接口。interfaceExpression{ voidexecute(Contextctx);}(三)三個(gè)具體終止表達(dá)式解釋器類。classSpaceExpressionimplementsExpression{//space原語 publicvoidexecute(Contextctx){ System.out.print(""); }}classPrintExpressionimplementsExpression{//print原語 Strings; PrintExpression(Strings){ this.s=s; } publicvoidexecute(Contextctx){ System.out.print(s); } }classBreakExpressionimplementsExpression{//break原語 publicvoidexecute(Contextctx){ System.out.println(); }}(四)LoopExpression.java:具體非終止表達(dá)式解釋器類。classLoopExpressionimplementsExpression{ intn; Vector<Expression>vec=newVector(); LoopExpression(Strings){ this.n=Integer.parseInt(s); } publicvoidaddExpression(Expressione){ vec.add(e); } publicvoidexecute(Contextctx){ for(inti=零;i<n;i++){ for(intj=零;j<vec.size();j++){ Expressionexp=vec.get(j); exp.execute(ctx); } } } }(五)Test.java:測(cè)試類。publicclassTest{ publicstaticvoidmain(String[]args){ System.out.println("Pleaseinputtheexpressionstring:"); Scannersc=newScanner(System.in); Strings=sc.nextLine(); Queue<Expression>qu=newLinkedList(); //初始化表達(dá)式隊(duì)列 StringTokenizerst=newStringTokenizer(s); while(st.hasMoreTokens()){ Stringu=st.nextToken(); if(u.equals("print")){ //若是print原語 Stringstr=st.nextToken(); //則產(chǎn)生Print對(duì)象 Expressione=newPrintExpression(str); qu.offer(e); //加入隊(duì)列 } if(u.equals("space")){ //若是space原語 Expressione=newSpaceExpression(); qu.offer(e); //加入隊(duì)列 } if(u.equal

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論