Java基于解释器模式实现定义一种简单的语言功能示例
作者:chengqiuming 发布时间:2021-06-18 15:53:42
本文实例讲述了Java基于解释器模式实现定义一种简单的语言功能。分享给大家供大家参考,具体如下:
一 模式定义
解释器模式:就是给定一个语言的文法表示,并且定义一个解释器,用来解释语言中的句子。解释器模式描述了怎样在有了一个简单的文法后,使用模式设计解释这些语句。
二 模式举例
1 模式分析
我们自己设计一种语言来说明这一模式
(1)该语言区分大小写
(2)该语言以PROGRAM开头,END结尾
(3)PRINTLN表示打印一行并换行
(4)使用FOR…FROM…TO…END表示循环
示例语言内容如下:
PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end...END
该句表示的意思是:首先打印“start…”换行,然后循环打印“90”换行、“91”换行、……“100”换行,最后打印“end…”换行。
2 该语言解释树结构
3 该语言解释器活动图
4 代码示例
4.1 创建上下文环境——Context
package com.demo.interpreter.context;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
/**
* 上下文环境
*
* @author
*
*/
public class Context {
// 待解析的文本内容
private final StringTokenizer stringTokenizer;
// 当前命令
private String currentToken;
// 用来存储动态变化信息内容
private final Map<String, Object> map = new HashMap<String, Object>();
/**
* 构造方法设置解析内容
*
* @param text
*/
public Context(String text) {
// 使用空格分隔待解析文本内容
this.stringTokenizer = new StringTokenizer(text);
}
/**
* 解析文本
*/
public String next() {
if (this.stringTokenizer.hasMoreTokens()) {
currentToken = this.stringTokenizer.nextToken();
} else {
currentToken = null;
}
return currentToken;
}
/**
* 判断命令是否正确
*
* @param command
* @return
*/
public boolean equalsWithCommand(String command) {
if (command == null || !command.equals(this.currentToken)) {
return false;
}
return true;
}
/**
* 获得当前命令内容
*
* @return
*/
public String getCurrentToken() {
return this.currentToken;
}
/**
* 获得节点的内容
*
* @return
*/
public String getTokenContent(String text) {
String str = text;
if (str != null) { // 替换map中的动态变化内容后返回 Iterator<String>
// 替换map中的动态变化内容后返回
Iterator<String> iterator = this.map.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Object obj = map.get(key);
str = str.replaceAll(key, obj.toString());
}
}
return str;
}
public void put(String key, Object value) {
this.map.put(key, value);
}
public void clear(String key) {
this.map.remove(key);
}
}
4.2 表达式接口——IExpressions
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
*
* 表达式接口
*
* @author
*
*/
public interface IExpressions {
/**
* 解析
*
* @param context
*/
public void parse(Context context);
/**
* 执行方法
*
* @param context
*/
public void interpret();
}
4.3 主表达式——ProgramExpression
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
* program 表达式
*
* @author
*
*/
public class ProgramExpression implements IExpressions {
// 上下文环境
private final Context context;
// 当前命令
private final static String COMMAND = "PROGRAM";
// 存储下一个表达式引用
private IExpressions expressions;
/**
* 构造方法将待解析的内容传入
*
* @param text
*/
public ProgramExpression(String text) {
this.context = new Context(text);
this.parse(this.context);
}
@Override
public void parse(Context context) {
// 获取第一个命令节点
this.context.next();
}
/**
* 实现解释方法
*/
@Override
public void interpret() {
// 判断是否是以PROGRAM 开始
if (!this.context.equalsWithCommand(COMMAND)) {
System.out.println("The '" + COMMAND + "' is Excepted For Start!");
} else {
// 是以PROGRAM 开始
this.context.next();
this.expressions = new ListExpression();
this.expressions.parse(this.context);
// ListExpression表达式开始解析
this.expressions.interpret();
}
}
}
4.4 列表表达式——ListExpression
package com.demo.interpreter.express;
import java.util.ArrayList;
import java.util.Iterator;
import com.demo.interpreter.context.Context;
/**
* 列表表达式
*
* @author
*
*/
public class ListExpression implements IExpressions {
private Context context;
private final ArrayList<IExpressions> list = new ArrayList<IExpressions>();
/**
* 构造方法将待解析的context传入
*
* @param context
*/
public void parse(Context context) {
this.context = context;
// 在ListExpression解析表达式中,循环解释语句中的每一个单词,直到终结符表达式或者异常情况退出
while (true) {
if (this.context.getCurrentToken() == null) {
// 获取当前节点如果为 null 则表示缺少END表达式
System.out.println("Error: The Experssion Missing 'END'! ");
break;
} else if (this.context.equalsWithCommand("END")) {
this.context.next();
// 解析正常结束
break;
} else {
// 建立Command 表达式
IExpressions expressions = new CommandExperssion(this.context);
// 添加到列表中
list.add(expressions);
}
}
}
/**
* 实现解释方法
*/
@Override
public void interpret() {
// 循环list列表中每一个表达式 解释执行
Iterator<IExpressions> iterator = list.iterator();
while (iterator.hasNext()) {
(iterator.next()).interpret();
}
}
}
4.5 命令表达式——CommandExperssion
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
* 命令表达式
*
* @author
*
*/
public class CommandExperssion implements IExpressions {
private final Context context;
private IExpressions expressions;
/**
* 构造方法将待解析的context传入
*
* @param context
*/
public CommandExperssion(Context context) {
this.context = context;
this.parse(this.context);
}
public void parse(Context context) {
// 判断当前命令类别 在此只对For和最原始命令进行区分
if (this.context.equalsWithCommand("FOR")) {
// 创建For表达式进行解析
expressions = new ForExpression(this.context);
} else {
// 创建原始命令表达式进行内容解析
expressions = new PrimitiveExpression(this.context);
}
}
/**
* 解析内容
*/
@Override
public void interpret() {
// 解析内容
this.expressions.interpret();
}
}
4.6 循环表达式——ForExpression
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
* For表达式
*
* @author
*
*/
public class ForExpression implements IExpressions {
private final Context context;
// 存储当前索引key值
private String variable;
// 存储循环起始位置
private int start_index;
// 存储循环结束位置
private int end_index;
private IExpressions expressions;
/**
* 构造方法将待解析的context传入
*
* @param context
*/
public ForExpression(Context context) {
this.context = context;
this.parse(this.context);
}
/**
* 解析表达式
*/
@Override
public void parse(Context context) {
// 首先获取当前节点
this.context.next();
while (true) {
// 判断节点
if (this.context.equalsWithCommand("FROM")) {
// 设置开始索引内容
String nextStr = this.context.next();
try {
this.start_index = Integer.parseInt(nextStr);
} catch (Exception e) {
System.out
.println("Error: After 'FROM' Expression Exist Error!Please Check the Format Of Expression is Correct!");
break;
}
// 获取下一个节点
this.context.next();
} else if (this.context.equalsWithCommand("TO")) {
// 设置结束索引内容
String nextStr = this.context.next();
try {
this.end_index = Integer.parseInt(nextStr);
} catch (Exception e) {
System.out
.println("Error: After 'TO' Expression Exist Error!Please Check the Format Of Expression is Correct!");
}
this.context.next();
break;
} else {
// 设置当前索引变量内容
if (this.variable == null) {
this.variable = this.context.getCurrentToken();
}
// 获取下一个节点
this.context.next();
}
}
// 建立列表表达式
this.expressions = new ListExpression();
this.expressions.parse(this.context);
}
/**
* 实现解释方法
*/
@Override
public void interpret() {
// 建立命令表达式
for (int x = this.start_index; x <= this.end_index; x++) {
// 设置变量内容
this.context.put("" + this.variable, x);
// 执行解释方法
this.expressions.interpret();
}
// 移除使用的临时变量内容
this.context.clear("" + this.variable);
}
}
4.7 基础表达式——PrimitiveExpression
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
* 最基础的表达式
*
* @author
*
*/
public class PrimitiveExpression implements IExpressions {
private Context context;
// 节点名称
private String tokenName;
// 文本内容
private String text;
/**
* 构造方法将待解析的context传入
*
* @param context
*/
public PrimitiveExpression(Context context) {
this.parse(context);
}
@Override
public void parse(Context context) {
this.context = context;
this.tokenName = this.context.getCurrentToken();
this.context.next();
if ("PRINTLN".equals(this.tokenName)) {
this.text = this.context.getCurrentToken();
this.context.next();
}
}
/**
* 实现解释方法
*/
@Override
public void interpret() {
// 首先获取当前节点内容
if ("PRINTLN".equals(tokenName)) {
// 获得内容信息
// 打印内容
System.out.println(this.context.getTokenContent(this.text));
}
}
}
4.8 让语言解释器开始工作——Client
package com.demo.interpreter;
import com.demo.interpreter.express.IExpressions;
import com.demo.interpreter.express.ProgramExpression;
/**
* 主应用程序
*
* @author
*
*/
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// myida语言语句
String str = "PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end... END";
System.out.println("str:" + str);
// 创建PROGRAM表达式
IExpressions expressions = new ProgramExpression(str);
// 解释执行
expressions.interpret();
}
}
5 运行结果
str:PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end... END
start...
90
91
92
93
94
95
96
97
98
99
100
end...
三 设计原则
1 “开-闭”原则
2 封闭变化原则
四 使用场合
(1)一种特定类型的问题发生的频率足够高,并且业务规则频繁变化,不断重复出现类似情况。
(2)业务规则不是过于复杂烦琐,比较容易抽象出语法规则。
(3)效率不是软件系统中主要考虑的因素。
五 解释器模式静态类图
更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。
来源:https://blog.csdn.net/chengqiuming/article/details/70139382
猜你喜欢
- 一:需求详情:OpenOffice.org 是一套跨平台的办公室软件套件,能在 Windows、Linux、MacOS X (X11)、和
- 双向顺序队列ArrayDeque和双向链式队列LinkedList,JDK已经包含,在此略。ArrayDeque包括顺序栈和顺序队列,Lin
- 本文实例讲述了Spring实战之协调作用域不同步的Bean操作。分享给大家供大家参考,具体如下:一 配置<?xml version=&
- 前言春节要到了,看惯了前端各种小游戏,确实做得很好,很精致。但是我也要为后端程序员稍微做一点贡献,做一款java版本的【年兽大作战】。这个游
- 自定义TypeHandler映射JSON类型为List1. 实体类这里只展示需要映射的字段,分别在所需映射的字段和实体类上添加注解。&nbs
- Android手势解锁本文讲述的是一个手势解锁的库,可以定制显示隐藏宫格点、路径、并且带有小九宫格显示图,和震动!让你学会使用这个简单,高效
- json格式的字符串与对象的互相转换Jackson 简介Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转
- 本文实例讲述了eclipse中自动生成javadoc文档的方法。分享给大家供大家参考。具体方法如下:使用eclipse生成文档(javado
- 消息都是存放在一个消息队列中去,而消息循环线程就是围绕这个消息队列进入一个无限循环的,直到线程退出。如果队列中有消息,消息循环线程就会把它取
- 在之前的博客使用SpringMVC创建Web工程并使用SpringSecurity进行权限控制的详细配置方法 中,我们描述了如何配置一个基于
- 首先,确保 IDEA 软件正确安装完成,Java 开发工具包 JDK 安装完成。IDEA 的 Java 项目 (Project) 则相当于
- 效果展示人脸支付效果视频密码框输入支付效果视频因为密码支付时会调起系统安全键盘,开启自动保护功能,防止泄露,会导致输入密码时录屏黑屏,故使用
- java中的复杂查询sql语句实现:这样的查询栏,在页面中很常见,这就是复杂查询的条件,我们可以填写一个条件或多个条件,也可以一个都不填写,
- 本文实例为大家分享了Springboot整合pagehelper分页展示的具体代码,供大家参考,具体内容如下一、添加依赖查找maven中pa
- java 方法签名,我想做java 开发的朋友也知道,方法签名的重要性,是方法重载的一个比较好的解释,尤其是在后续优化方面,这里记录下,有看
- Spring security 重写Filter实现json登录在使用SpringSecurity中,大伙都知道默认的登录数据是通过key/
- 核心考点:链表操作,临界条件检查,特殊情况处理在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针
- 异步方法很好的解决了这些问题,异步执行某个方法,程序立即开辟一个新线程去运行你的方法,主线程包括界面就不会死掉了。异步如何开始,好理解,现在
- 前言今天收到一封邮件,大概内容如下:spring boot鼓励去配置化,那么怎么将第三方jar包中的xml去配置化了?其实,这个问题,在前面
- 一,FileWritter写入文件FileWritter, 字符流写入字符到文件。默认情况下,它会使用新的内容取代所有现有的内容,然而,当指