解释器模式 我会带着你远行 2023-07-13 08:28 122阅读 0赞 ### 解释器模式 ### * * 1 定义 * 2 解释器模式结构图 * 3 代码实现 * 4 具体实例 * 5 优缺点及适用场景 ## 1 定义 ## **解释器模式**:定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的"语言"是指适用规定格式和语法的代码.解释器模式是一种类行为型模式. ## 2 解释器模式结构图 ## ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L211c2lfbQ_size_16_color_FFFFFF_t_70] AbstractExpression(抽象表达式):在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。 TerminalExpression(终结符表达式):终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常在一个解释器模式中只有少数几个终结符表达式类,它们的实例可以通过非终结符表达式组成较为复杂的句子。 NonterminalExpression(非终结符表达式):非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。 Context(环境类):环境类又称为上下文类,它用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。 ## 3 代码实现 ## abstract class AbstractExpression{ public abstract void interpret(Context ctx); } class TerminalExpression extends AbstractExpression{ public void interpret(Context ctx){ //终结符表达式的解释操作 } } class NonterminalExpression extends AbstractExpression{ private AbstractExpression left; private AbstractExpression rigth; public NonterminalExpression(AbstractExpression left,AbstractExpression right){ this.left = left; this.right = right; } public void interpret(Context ctx){ //递归调用每一个组成部分的interpret()方法 //在诋毁调用时指定组成部分的连接方式,即非终结符的功能 } } class Context{ private HashMap map = new HashMap(); public void assign(String key,String value){ //往环境类中设置 } public String lookup(String key){ //获取存储在环境类中的值 } } ## 4 具体实例 ## 开发一套简单的基于字符界面的格式化指令,可以根据输入的指令在字符界面中输出一些格式化内容 ,例如输入"LOOP 2 PRINT 杨过 SPACE SPACE PRINT 小龙女 BREAK END PRINT 郭靖 SPACE SPACE PRINT 黄蓉".将输出如下结果: ![在这里插入图片描述][20200311141155804.png] 代码如下: public abstract class Node { public abstract void interpret(Context context);//声明一个方法用于解释 public abstract void execute();//声明一个方法用于执行标记对应的命令 } public class Context { private StringTokenizer tokenizer; private String currentToken; //当前字符串标记 public Context(String text){ tokenizer = new StringTokenizer(text); nextToken(); } public String nextToken(){ if(tokenizer.hasMoreTokens()){ currentToken = tokenizer.nextToken(); }else { currentToken = null; } return currentToken; } // 返回当前的标记 public String currentToken(){ return currentToken; } public void skipToken(String token){ if(!token.equals(currentToken)){ System.out.println("错误提示:" + currentToken + "解释错误!"); } nextToken(); } // 如果当前的标记是一个数字,则返回对应的数值 public int currentNumber(){ int number = 0; try{ number = Integer.parseInt(currentToken);//将字符串转换成整数 }catch (NumberFormatException e){ System.out.println("错误提示:"+e); } return number; } } public class ExpressionNode extends Node { private ArrayList<Node> list = new ArrayList<Node>(); @Override public void interpret(Context context) { //循环处理context中的标记 int i=0; while(true){ i++; if(context.currentToken() == null){ //如果没有任何标记,则退出解释 break; }else if(context.currentToken().equals("END")){ //如果标记为end,不解释END并结束本次解释过程,可以继续之后的解释 context.skipToken("END"); break; }else{ //如果为其他标记,则解释标记并将其加入命令集合 Node commandNode = new CommandNode(); commandNode.interpret(context); list.add(commandNode); } } } @Override public void execute() { Iterator iterator = list.iterator(); while (iterator.hasNext()){ Node node = (Node) iterator.next(); node.execute(); } } } public class CommandNode extends Node { private String nodeName = "CommandNode"; private Node node; @Override public void interpret(Context context) { if(context.currentToken().equals("LOOP")){ //处理循环命令 node = new LoopCommandNode(); node.interpret(context); }else{ //处理其他基本命令 node = new PrimitiveCommandNode(); node.interpret(context); } } @Override public void execute() { node.execute(); } } public class LoopCommandNode extends Node{ private int number;//循环次数 private Node commandNode;//循环语句中的表达式 //解释循环命令 @Override public void interpret(Context context) { context.skipToken("LOOP"); number = context.currentNumber(); context.nextToken(); commandNode = new ExpressionNode();//循环语句中的表达式 commandNode.interpret(context); } @Override public void execute() { for (int i = 0; i < number; i++) { commandNode.execute(); } } } public class PrimitiveCommandNode extends Node { private String name; private String text; //解释基本命令 @Override public void interpret(Context context) { name = context.currentToken(); context.skipToken(name); if(!name.equals("PRINT") && !name.equals("BREAK") && !name.equals("END") && !name.equals("LOOP") && !name.equals("SPACE")){ System.out.println("非法命令:" + name); } if(name.equals("PRINT")){ text = context.currentToken(); context.nextToken(); } } @Override public void execute() { if(name.equals("PRINT")){ System.out.print(text); }else if(name.equals("SPACE")){ System.out.print(" "); }else if(name.equals("BREAK")){ System.out.println(); } } } public class Client { public static void main(String[] args) { String text = "LOOP 2 PRINT 杨过 SPACE SPACE PRINT 小龙女 BREAK END PRINT 郭靖 SPACE SPACE PRINT 黄蓉"; Context context = new Context(text); Node node = new ExpressionNode(); node.interpret(context); node.execute(); } } ## 5 优缺点及适用场景 ## 主要优点: 1)易于改变和扩展文法.由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法。 2)每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。 3)实现文法较为容易。在抽象语法树中每一个表达式节点类的实现方式都是相似的,这些类的代码编写都不会特别复杂,还可以通过一些工具自动生成节点类代码。 4)增加新的解释表达式较为方便。如果用户需要增加新的解释表达式只需要对应增加一个新的终结符表达式或非终结符表达式类,原有表达式类代码无须修改,符合“开闭原则”。 主要缺点: 1)对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。 2)执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。 适用场景: 1)可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2)一些重复出现的问题可以用一种简单的语言来进行表达。 3)一个语言的文法较为简单。 4)执行效率不是关键问题。【注:高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。】 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L211c2lfbQ_size_16_color_FFFFFF_t_70]: https://img-blog.csdnimg.cn/20200311135040549.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L211c2lfbQ==,size_16,color_FFFFFF,t_70 [20200311141155804.png]: https://img-blog.csdnimg.cn/20200311141155804.png
相关 解释器模式 概述 ![watermark_type_d3F5LXplbmhlaQ_shadow_50_text_Q1NETiBA5rW35rex5LiN6KeB6bK4_size_1 男娘i/ 2023年10月03日 18:21/ 0 赞/ 30 阅读
相关 设计模式——解释器模式 设计模式——解释器模式 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly 客官°小女子只卖身不卖艺/ 2022年12月29日 14:16/ 0 赞/ 318 阅读
相关 解释器模式 转载:[解释器模式 - C语言中文网][- C] > 在软件开发中,会遇到有些问题多次重复出现,而且有一定的相似性和规律性。如果将它们归纳成一种简单的语言,那么这些问题实例将 Bertha 。/ 2022年09月01日 14:49/ 0 赞/ 304 阅读
相关 解释器模式 解释器模式 定义: 提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。 解释器角色: 抽 电玩女神/ 2022年07月13日 12:48/ 0 赞/ 336 阅读
相关 解释器模式 1.使用场景: 这个设计模式一般用来解释语句中的句子,实际开发中EL表达式或者正则表达式的解释器就是采用这种设计模式等。 2.UML表示 Expression:抽 柔情只为你懂/ 2022年05月31日 09:27/ 0 赞/ 330 阅读
相关 设计模式 : 解释器模式 解释器模式(interpreter) : 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 解释器模式需要解决的是 以你之姓@/ 2022年05月27日 07:57/ 0 赞/ 365 阅读
相关 解释器模式 前言 解释器模式(Interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器吗,这个解释器使用该表示来解释语言中的句子。 一、抽象表达式 矫情吗;*/ 2021年12月09日 00:55/ 0 赞/ 444 阅读
相关 解释器模式 23.解释器模式 ![70][] class Program { static void Main(string[] a Dear 丶/ 2021年09月17日 00:08/ 0 赞/ 487 阅读
相关 解释器模式 释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式... 小灰灰/ 2020年06月13日 05:43/ 0 赞/ 799 阅读
还没有评论,来说两句吧...