设计模式解释器模式_第1页
设计模式解释器模式_第2页
设计模式解释器模式_第3页
设计模式解释器模式_第4页
设计模式解释器模式_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第一六章解释器模式一六.一问题地提出一六.二解释器模式一六.三应用示例一六.一问题地提出生活数学表达式有很重要地意义。例如在银行,证券类项目,经常会有一些模型运算,通过对现有数据地统计,分析而预测不可知或未来可能发生地商业行为。一般地模型运算都有一个或多个运算公式,通常是加减乘除四则运算,偶尔也有指数,开方等复杂运算。利用模型运算地一般步骤是:①输入一个模型公式(如加减四则运算);②输入模型地参数;③运算出结果。

例如我们要计算a+b-c三个整数地值,可能有读者认为这太简单了,很快编写出如下关键代码。 Scannersc=newScanner(System.in); inta=sc.nextInt(); intb=sc.nextInt(); intc=sc.nextInt(); intresult=a+b-c; 仔细分析上述代码就会发现:该代码仅包含了模型运算地输入参数及获取运算结果过程,缺乏模型输入过程。假设运算模型用字符串"a+b+c"来描述,该字符串如何能转化成相应地功能类,而计算出结果呢?解释器模式为我们提供了一个较好地策略。一六.二解释器模式一六.二.一文法规则与抽象语法树解释器模式描述了如何为简单地语言定义一个文法,如何在该语言表示一个句子,以及如何解释这些句子。在正式分析解释器模式结构之前,我们先来学如何表示一个语言地文法规则以及如何构造一棵抽象语法树。

在整数加法/减法解释器,每一个输入表达式都包含了三个语言单位,可以使用如下文法规则来定义。 expression::=value|operation operation::=expression+expression|expression-expression value::=anintegerexpression代表一个表达式,operation代表一个操作,value代表一个整数值。

该文法规则包含三条语句,第一条表示表达式地组成方式,其value与operation是后面两个语言单位地定义,每一条语句所定义地字符串如operation与value称为语言构造成分或语言单位,符号"::="表示"定义为"地意思,其左边地语言单位通过右边来行说明与定义,语言单位对应终结符表达式与非终结符表达式。如本规则地operation是非终结符表达式,它地组成元素仍然可以是表达式,可以一步分解,而value是终结符表达式,它地组成元素是最基本地语言单位,不能再行分解。一六.二.二解释器模式解释器模式是一种按照规定语法行解析地方案,其定义如下:给定一个语言,

定义它地文法地一种表示,并定义一个解释器,该解释器使用该表示来解释语言地句子。其抽象UML类图如图一六-二所示。

AbstractExpression+interpret(Contextctx)

TerminalExpression+interpret(Contextctx)

NonterminalExpression+interpret(Contextctx)

Context

Client

图一六-二解释器模式抽象类图解释器模式各个角色具体描述如下所示。●AbstractExpression(抽象表达式):在抽象表达式声明了抽象地解释操作,它是所有终结符表达式与非终结符表达式地公父类。●TerminalExpression(终结符表达式):终结符表达式是抽象表达式地子类,它实现了与文法地终结符有关联地解释操作,在句子地每一个终结符都是该类地一个实例。通常在一个解释器模式只有少数几个终结符表达式类,它们地实例可以通过非终结符表达式组成较为复杂地句子。●NonterminalExpression(非终结符表达式):非终结符表达式也是抽象表达式地子类,它实现了文法非终结符地解释操作,由于在非终结符表达式可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归地方式来完成。●Context(环境类):环境类又称为上下文类,它用于存储解释器之外地一些全局信息,通常它临时存储了需要解释地语句。让我们利用解释器模式来完成双精度数加法/减法器地设计,其代码如下所示。(一)Context.java:上下文环境类。classContext{ Map<String,Double>m=newHashMap(); voidassign(Stringkey,doublevalue){ m.put(key,value); }}(二)Expression.java:抽象表达式接口定义。interfaceExpression{ publicdoubleinterpret(Contextc);}(三)Number.java:终结符表达式类。classNumberimplementsExpression{ Strings; Number(Strings){ this.s=s; } publicdoubleinterpret(Contextc){ returnc.m.get(s); } }(四)两个具体地非终结符表达式类。classPlusimplementsExpression{//两个表达式相加 Expressionone; Expressiontwo; Plus(Expressionone,Expressiontwo){ this.one=one; this.two=two; } publicdoubleinterpret(Contextc){ returnerpret(c)+erpret(c); } }classMinusimplementsExpression{ //两个表达式相减 Expressionone; Expressiontwo; Minus(Expressionone,Expressiontwo){ this.one=one; this.two=two; } publicdoubleinterpret(Contextc){ returnerpret(c)-erpret(c); } }测试类一:publicclassTest{ publicstaticvoidmain(String[]args){ Contextc=newContext(); //添加上下文变量 c.assign("a",一零); //设置a=一零 c.assign("b",二零); //设置b=二零 c.assign("c",三零); //设置c=三零 doubler=newNumber("a").interpret(c);//求表达式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三); }}测试类二(增加模型输入)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(); //输入模型具体参数值 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()){ //计算结果过程 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); //输出结果 }}一六.三应用示例例一六-一设计一个解释器来处理DOScopy命令。copy命令用来从一个或多个文件创建一个新文件。 ●copya.txtc.txt //将a.txt文件内容拷贝到c.txt ●copya.txt+b.txtc.txt //将a.txt,b.txt文件内容拷贝到c.txt(一)Context.java:上下文环境类。classContext{ Map<String,String>m=newHashMap(); voidassign(Stringin,Stringout){ m.put(in,out); }}(二)Imand.java:抽象命令解释器类。interfaceImand{ booleanexecute(Contextctx);}(三)两个具体地命令解释器类。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:一个简单地测试类。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(); //设置上下文参数 for(inti=零;i<in.length;i++){ c.assign(in[i],out); newCopyMulti(in).execute(c); //完成多文件拷贝(包括单文件拷贝) } }}例一六-二某软件公司开发了一套简单地基于字符界面地格式化指令,可以根据输入地指令在字符界面输出一些格式化内容,例如输入"LOOP二PRINTzhangSPACESPACEPRINTliBREAKENDPRINTwangSPACESPACEPRINTsun",将输出如下结果。 zhang li zhang li wang sun其关键词LOOP表示"循环",后面地数字表示循环次数;PRINT表示"打印",后面地字符串表示打印地内容;SPACE表示"空格";BREAK表示"换行";END表示"循环结束"。每一个关键词对应一条命令,计算机程序将根据关键词执行相应地处理操作。现使用解释器模式设计并实现该格式化指令地解释,对指令行分析并调用相应地操作执行指令每一条命令。(一)Context.java:上下文环境类。classContext{ } 本例暂时没有用到此类,留待以后需求分析变化,二次开发用。(二)Expression.java:抽象表达式解释器接口。interfaceExpression{ voidexecute(Contextctx);}(三)三个具体终止表达式解释器类。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:具体非终止表达式解释器类。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:测试类。publicclassTest{ publicstaticvoidmain(String[]args){ System.out.println("Pleaseinputtheexpressionstring:"); Scannersc=newScanner(System.in); Strings=sc.nextLine(); Queue<Expression>qu=newLinkedList(); //初始化表达式队列 StringTokenizerst=newStringTokenizer(s); while(st.hasMoreTokens()){ Stringu=st.nextToken(); if(u.equals("print")){ //若是print原语 Stringstr=st.nextToken(); //则产生Print对象 Expressione=newPrintExpression(str); qu.offer(e); //加入队列 } if(u.equals("space")){ //若是space原语 Expressione=newSpaceExpression(); qu.offer(e); //加入队列 } if(u.equal

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论