Java基于解釋器模式實現(xiàn)定義一種簡單的語言功能示例
本文實例講述了Java基于解釋器模式實現(xiàn)定義一種簡單的語言功能。分享給大家供大家參考,具體如下:
一 模式定義
解釋器模式:就是給定一個語言的文法表示,并且定義一個解釋器,用來解釋語言中的句子。解釋器模式描述了怎樣在有了一個簡單的文法后,使用模式設(shè)計解釋這些語句。
二 模式舉例
1 模式分析
我們自己設(shè)計一種語言來說明這一模式
(1)該語言區(qū)分大小寫
(2)該語言以PROGRAM開頭,END結(jié)尾
(3)PRINTLN表示打印一行并換行
(4)使用FOR…FROM…TO…END表示循環(huán)
示例語言內(nèi)容如下:
PROGRAM PRINTLN start... FOR i FROM 90 TO 100 PRINTLN i END PRINTLN end...END
該句表示的意思是:首先打印“start…”換行,然后循環(huán)打印“90”換行、“91”換行、……“100”換行,最后打印“end…”換行。
2 該語言解釋樹結(jié)構(gòu)

3 該語言解釋器活動圖

4 代碼示例
4.1 創(chuàng)建上下文環(huán)境——Context
package com.demo.interpreter.context;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
/**
* 上下文環(huán)境
*
* @author
*
*/
public class Context {
// 待解析的文本內(nèi)容
private final StringTokenizer stringTokenizer;
// 當前命令
private String currentToken;
// 用來存儲動態(tài)變化信息內(nèi)容
private final Map<String, Object> map = new HashMap<String, Object>();
/**
* 構(gòu)造方法設(shè)置解析內(nèi)容
*
* @param text
*/
public Context(String text) {
// 使用空格分隔待解析文本內(nèi)容
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;
}
/**
* 獲得當前命令內(nèi)容
*
* @return
*/
public String getCurrentToken() {
return this.currentToken;
}
/**
* 獲得節(jié)點的內(nèi)容
*
* @return
*/
public String getTokenContent(String text) {
String str = text;
if (str != null) { // 替換map中的動態(tài)變化內(nèi)容后返回 Iterator<String>
// 替換map中的動態(tài)變化內(nèi)容后返回
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);
/**
* 執(zhí)行方法
*
* @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 {
// 上下文環(huán)境
private final Context context;
// 當前命令
private final static String COMMAND = "PROGRAM";
// 存儲下一個表達式引用
private IExpressions expressions;
/**
* 構(gòu)造方法將待解析的內(nèi)容傳入
*
* @param text
*/
public ProgramExpression(String text) {
this.context = new Context(text);
this.parse(this.context);
}
@Override
public void parse(Context context) {
// 獲取第一個命令節(jié)點
this.context.next();
}
/**
* 實現(xiàn)解釋方法
*/
@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>();
/**
* 構(gòu)造方法將待解析的context傳入
*
* @param context
*/
public void parse(Context context) {
this.context = context;
// 在ListExpression解析表達式中,循環(huán)解釋語句中的每一個單詞,直到終結(jié)符表達式或者異常情況退出
while (true) {
if (this.context.getCurrentToken() == null) {
// 獲取當前節(jié)點如果為 null 則表示缺少END表達式
System.out.println("Error: The Experssion Missing 'END'! ");
break;
} else if (this.context.equalsWithCommand("END")) {
this.context.next();
// 解析正常結(jié)束
break;
} else {
// 建立Command 表達式
IExpressions expressions = new CommandExperssion(this.context);
// 添加到列表中
list.add(expressions);
}
}
}
/**
* 實現(xiàn)解釋方法
*/
@Override
public void interpret() {
// 循環(huán)list列表中每一個表達式 解釋執(zhí)行
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;
/**
* 構(gòu)造方法將待解析的context傳入
*
* @param context
*/
public CommandExperssion(Context context) {
this.context = context;
this.parse(this.context);
}
public void parse(Context context) {
// 判斷當前命令類別 在此只對For和最原始命令進行區(qū)分
if (this.context.equalsWithCommand("FOR")) {
// 創(chuàng)建For表達式進行解析
expressions = new ForExpression(this.context);
} else {
// 創(chuàng)建原始命令表達式進行內(nèi)容解析
expressions = new PrimitiveExpression(this.context);
}
}
/**
* 解析內(nèi)容
*/
@Override
public void interpret() {
// 解析內(nèi)容
this.expressions.interpret();
}
}
4.6 循環(huán)表達式——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;
// 存儲循環(huán)起始位置
private int start_index;
// 存儲循環(huán)結(jié)束位置
private int end_index;
private IExpressions expressions;
/**
* 構(gòu)造方法將待解析的context傳入
*
* @param context
*/
public ForExpression(Context context) {
this.context = context;
this.parse(this.context);
}
/**
* 解析表達式
*/
@Override
public void parse(Context context) {
// 首先獲取當前節(jié)點
this.context.next();
while (true) {
// 判斷節(jié)點
if (this.context.equalsWithCommand("FROM")) {
// 設(shè)置開始索引內(nèi)容
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;
}
// 獲取下一個節(jié)點
this.context.next();
} else if (this.context.equalsWithCommand("TO")) {
// 設(shè)置結(jié)束索引內(nèi)容
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 {
// 設(shè)置當前索引變量內(nèi)容
if (this.variable == null) {
this.variable = this.context.getCurrentToken();
}
// 獲取下一個節(jié)點
this.context.next();
}
}
// 建立列表表達式
this.expressions = new ListExpression();
this.expressions.parse(this.context);
}
/**
* 實現(xiàn)解釋方法
*/
@Override
public void interpret() {
// 建立命令表達式
for (int x = this.start_index; x <= this.end_index; x++) {
// 設(shè)置變量內(nèi)容
this.context.put("" + this.variable, x);
// 執(zhí)行解釋方法
this.expressions.interpret();
}
// 移除使用的臨時變量內(nèi)容
this.context.clear("" + this.variable);
}
}
4.7 基礎(chǔ)表達式——PrimitiveExpression
package com.demo.interpreter.express;
import com.demo.interpreter.context.Context;
/**
* 最基礎(chǔ)的表達式
*
* @author
*
*/
public class PrimitiveExpression implements IExpressions {
private Context context;
// 節(jié)點名稱
private String tokenName;
// 文本內(nèi)容
private String text;
/**
* 構(gòu)造方法將待解析的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();
}
}
/**
* 實現(xiàn)解釋方法
*/
@Override
public void interpret() {
// 首先獲取當前節(jié)點內(nèi)容
if ("PRINTLN".equals(tokenName)) {
// 獲得內(nèi)容信息
// 打印內(nèi)容
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;
/**
* 主應(yīng)用程序
*
* @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);
// 創(chuàng)建PROGRAM表達式
IExpressions expressions = new ProgramExpression(str);
// 解釋執(zhí)行
expressions.interpret();
}
}
5 運行結(jié)果
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...
三 設(shè)計原則
1 “開-閉”原則
2 封閉變化原則
四 使用場合
(1)一種特定類型的問題發(fā)生的頻率足夠高,并且業(yè)務(wù)規(guī)則頻繁變化,不斷重復(fù)出現(xiàn)類似情況。
(2)業(yè)務(wù)規(guī)則不是過于復(fù)雜煩瑣,比較容易抽象出語法規(guī)則。
(3)效率不是軟件系統(tǒng)中主要考慮的因素。
五 解釋器模式靜態(tài)類圖

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
SpringBoot集成Redis及SpringCache緩存管理示例詳解
本文介紹了如何在SpringBoot中集成Redis并使用SpringCache進行緩存管理,詳解了Redis的配置、使用以及SpringCache的注解,還闡述了SpringCache的工作原理,包括其AOP實現(xiàn)和與各種緩存框架的集成,使得開發(fā)者可以輕松實現(xiàn)緩存功能,以提高應(yīng)用性能2024-09-09
Java springboot Mongodb增刪改查代碼實例
這篇文章主要介紹了Java springboot Mongodb增刪改查代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-07-07
解決使用json-lib包實現(xiàn)xml轉(zhuǎn)json時空值被轉(zhuǎn)為空中括號的問題
網(wǎng)上能查到的xml轉(zhuǎn)json的jar包大部分是net.sf.json-lib,但是JSON json =xmlSerializer.read(xml); 方法會出現(xiàn)將空值轉(zhuǎn)化為[]的問題,下面為大家提供兩種解決方法2018-03-03
Java如何發(fā)起http請求的實現(xiàn)(GET/POST)
這篇文章主要介紹了Java如何發(fā)起http請求的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03

