设计模式之:解释器模式

目录

  • 解释器模式概述
  • 文法规则和抽象语法树
  • 解释器模式的结构与实现
  • 解释器模式的应用实例
  • 解释器模式的优缺点与适用环境

解释器模式概述

加法/减法解释器示意图:

image

分析:C#语言无法直接解释类似“1 + 2 + 3 – 4 + 1”这样的字符串。定义一套文法规则来实现对这些语句的解释,即设计一个自定义语言。基于现有的编程语言 -> 面向对象编程语言 -> 解释器模式。

解释器模式定义:

  • 解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
  • Interpreter Pattern: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
  • 类行为型模式

注:

  • 在解释器模式的定义中所指的“语言”是使用规定格式和语法的代码
  • 是一种使用频率相对较低但学习难度相对较大的设计模式,用于描述如何使用面向对象语言构成一个简单的语言解释器
  • 能够加深对面向对象思想的理解,并且理解编程语言中文法规则的解释过程

文法规则和抽象语法树

文法规则:

  • 1 + 2 + 3 – 4 + 1

expression ::= value | operation

operation ::= expression ‘+’ expression | expression ‘-‘ expression

value ::= an integer //一个整数值

  • “::=”表示“定义为”
  • “|”表示“或”
  • “{”和“}”表示“组合”
  • “*”表示“出现0次或多次”

抽象语法树:抽象语法树(Abstract Syntax Tree, AST):描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符类和非终结符类

image

其中的operation节点为“非终结符表达式”,value为“终结符表达式”

解释器模式的结构与实现

解释器模式的结构:

image

解释器模式包含以下4个角色:

  • AbstractExpression(抽象表达式)

在抽象表达式中声明了抽象的解释操作,它是所有的终结符表达式和非终结符表达式的公共父类。

  • TerminalExpression(终结符表达式)

终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。通常在一个解释器模式中只有少数几个终结符表达式类,他们的实例可以通过非终结符表达式组成较为复杂的句子。

  • NonterminalExpression(非终结符表达式)

非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,由于在非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释 操作一般通过递归的方式来完成。

  • Context(环境类)

环境类又称为上下文类,他用于存储解释器之外的一些全局信息,通常它临时存储了需要解释器的语句。

  • Client(客户类)

在客户类中构造了表示该文法定义的语言中一个特定句子的抽象语法树,该抽象语法树由非终结符表达式和终结符表达式实例组合而成,在客户类中还将调用解释操作,实现对句子的解释。有时候为了简化客户类的代码,可以将抽象语法树的构造工作封装到专门的类中完成,客户端只需要提供待解释的句子并调用该类的解释操作即可,该类可以称为解释器封装类。

解释器模式的实现

典型的抽象表达式类代码:

public abstract class AbstractExpression
{
	public abstract void interpret(Context ctx);
} 

典型的终结符表达式类代码:

public class TerminalExpression extends AbstractExpression
{
	public void interpret(Context ctx)
	{
		//对于终结符表达式的解释操作
	}
} 

典型的非终结符表达式类代码:

public class NonterminalExpression extends AbstractExpression
{
	private AbstractExpression left;
	private AbstractExpression right;
	
	public NonterminalExpression(AbstractExpression left,AbstractExpression right)
	{
		this.left=left;
		this.right=right;
	}
	
	public void interpret(Context ctx)
	{
		//递归调用每一个组成部分的interpret()方法
		//在递归调用时指定组成部分的连接方式,即非终结符的功能
	}	
} 

典型的环境类代码:

环境类Context:

  • 用于存储一些全局信息,一般包含一个Hashtable或List等类型的集合对象(也可以直接由Hashtable等集合类充当环境类),存储一系列公共信息,例如变量名与值的映射关系(key/value)等,用于在执行具体的解释操作时从中获取相关信息
  • 可以在环境类中增加一些所有表达式解释器都共有的功能,以减轻解释器的职责
  • 当系统无须提供全局公共信息时可以省略环境类,根据实际情况决定是否需要环境类
public class Context
{
    	private HashMap map = new HashMap();
    	public void assign(String key, String value)
    	{
        	//往环境类中设值
  	}
	public String lookup(String key)    
	{
        	//获取存储在环境类中的值
    	}
} 

解释器模式的应用实例

实例:数学运算解释器

现需要构造一个语言解释器,使得系统可以执行整数间的乘、除和求模运算。如用户输入表达式“3 * 4 / 2 % 4”,输出结果为2。使用解释器模式实现该功能。

实例类图:

image

实例解析:

image

实例二:

某软件公司要开发一套机器人控制程序,在该机器人控制程序中包含一些简单的英文控制指令,每一个指令对应一个表达式(expression),该表达式可以是简单表达式也可以是复合表达式。每一个简单表达式由移动方向(direction),移动方式(action)和移动距离(distance)三部分组成,其中,移动方向包括向上(up)、向下(down)、向左(left)、向右(right);移动方式包括移动(move)和快速移动(run);移动距离为一个正整数。两个表达式之间可以通过与(and)连接,形成复合(composite)表达式。

用户通过对图形化的设置界面进行操作可以创建一个机器人控制指令,机器人在收到指令后将按照指令的设置进行移动,例如输入控制指令“up move 5”将“向上移动5个单位”;输入控制指令“down run 10 and left move 20”将“向下快速移动10个单位再向左移动20个单位”。

现使用解释器模式来设计该程序并模拟实现。

实例分析及类图

文法规则:

expression ::= direction action distance | composite //表达式

composite ::= expression ‘and’ expression //复合表达式

direction ::= ‘up’ | ‘down’ | ‘left’ | ‘right’ //移动方向

action ::= ‘move’ | ‘run’ //移动方式

distance ::= an integer //移动距离

  • 终结符表达式direction、action和distance对应DirectionNode类、ActionNode类和DistanceNode类
  • 非终结符表达式expression和composite对应SentenceNode类和AndNode类

抽象语法树:

  • down run 10 and left move 20

image

实例分析及类图:

image

实例代码:

  • (1) AbstractNode:抽象结点类,充当抽象表达式角色
  • (2) AndNode:And结点类,充当非终结符表达式角色
  • (3) SentenceNode:简单句子结点类,充当非终结符表达式角色
  • (4) DirectionNode:方向结点类,充当终结符表达式角色
  • (5) ActionNode:动作结点类,充当终结符表达式角色
  • (6) DistanceNode:距离结点类,充当终结符表达式角色
  • (7) InstructionHandler:指令处理类,工具类
  • (8) Program:客户端测试类

结果及分析:

down run 10 and left move 20

image

向下快速移动10再向左移动20

image

up move 5 and down run 10 and left move 5

image

向上移动5再向下快速移动10再向左移动5

解释器模式的优缺点与适用环境

模式优点:

  • 易于改变和扩展文法
  • 可以方便地实现一个简单的语言
  • 实现文法较为容易(有自动生成工具)
  • 增加新的解释表达式较为方便

模式缺点:

  • 对于复杂文法难以维护
  • 执行效率较低

模式适用环境:

  • 可以将一个需要解释执行的语言中的句子表示为一棵抽象语法树
  • 一些重复出现的问题可以用一种简单的语言来进行表达
  • 一个语言的文法较为简单
  • 执行效率不是关键问题

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一种语言文法的表示,并定义了一个解释器,用于解释语言中的句子。它将一个问题分成两个部分:一部分是语言的文法规则,另一部分是解释器,用来解释规则中的句子。解释器模式可以用于处理一些简单的语言,如数学表达式、正则表达式等。 实现方式: 1. 定义抽象表达式类(AbstractExpression),它是所有表达式类的父类,声明了抽象的解释方法。 2. 定义终结符表达式类(TerminalExpression),它实现了抽象表达式类中的解释方法,用于解释语言中的终结符。 3. 定义非终结符表达式类(NonterminalExpression),它也实现了抽象表达式类中的解释方法,用于解释语言中的非终结符。 4. 定义上下文类(Context),它包含了解释器需要的一些全局信息。 5. 客户端使用时,先创建一个上下文对象,然后将需要解释的语言句子作为参数传入解释器对象中,解释器对象将句子解释成相应的结果。 优点: 1. 可扩展性好,增加新的文法规则只需要添加相应的非终结符表达式类即可。 2. 易于实现语法分析。 缺点: 1. 对于复杂的文法规则,解释器模式的类数量可能会很大,增加程序的复杂性。 2. 执行效率较低,因为需要递归调用解释器对象。 适用场景: 1. 可以用于处理一些简单的语言,如数学表达式、正则表达式等。 2. 当语言的文法规则比较复杂时,可以使用解释器模式进行语法分析。 3. 当需要对语言进行增强时,可以使用解释器模式添加新的文法规则。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值