解释器模式
1、解释器模式介绍
解释器模式(Interpreter Pattern)是一种行为设计模式,它定义了一个语言的语法表示,并且使用解释器来解释这个语法。
该模式的核心思想是将一个语言表达式表示为一个抽象语法树,然后定义解释器来遍历这棵语法树并执行相应的操作。解释器模式常用于处理特定的语法或规则,并且可以根据需求进行灵活的扩展。
1.1 解释器模式基本实现
解释器模式结构图:
以下是解释器模式的关键角色:
- 抽象表达式(Abstract Expression):定义了解释器的接口,其中包含了一个抽象的interpret()方法,所有具体表达式都必须实现这个接口。
- 终结符表达式(Terminal Expression):实现了抽象表达式接口,并表示语法中的终结符(即不可再分的最小单元),例如变量或常量。
- 非终结符表达式(Non-terminal Expression):实现了抽象表达式接口,并表示语法中的非终结符,即可以由其他表达式组合而成的复杂表达式。
- 上下文(Context):包含解释器解释的上下文信息,一般是一个包含了各种全局信息的数据结构。
解释器模式的工作流程如下:
- 客户端创建并配置解释器的上下文。
- 客户端创建具体的解释器对象,并用抽象表达式接口进行引用。
- 客户端将表达式构建成抽象语法树。
- 客户端调用解释器的interpret()方法,传入上下文对象,执行解释操作。
AbstractExpression(抽象表达式),声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
/*** @author Shier* CreateTime 2023/5/24 19:27* 抽象表达式*/
public abstract class AbstractExpression {/*** 解释操作 - 类似翻译* @param context*/public abstract void interpret(Context context);
}
TerminalExpression(终结符表达式),实现与文法中的终结符相关联 的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()方 法。文法中每一个终结符都有一个具体终结表达式与之相对应。
/*** @author Shier* CreateTime 2023/5/24 19:29* 终结者表达式*/
public class TerminalExpression extends AbstractExpression{@Overridepublic void interpret(Context context) {System.out.println("终端解释器");}
}
NonterminalExpression(非终结符表达式),为文法中的非终结符实现 解释操作。对文法中每一条规则R1、R2、…、Rn都需要一个具体的非终结符 表达式类。通过实现抽象表达式的interpret()方法实现解释操作。解释操 作以递归方式调用上面所提到的代表R1、R2、…、Rn中各个符号的实例变量。
/*** @author Shier* CreateTime 2023/5/24 19:29* 非终结者表达式*/
public class NotTerminalExpression extends AbstractExpression{@Overridepublic void interpret(Context context) {System.out.println("非终端解释器");}
}
Context,包含解释器之外的一些全局信息。
/*** @author Shier* CreateTime 2023/5/24 19:31* 解释器外的全局信息*/
public class Context {private String input;private String outPut;public String getInput() {return input;}public void setInput(String input) {this.input = input;}public String getOutPut() {return outPut;}public void setOutPut(String outPut) {this.outPut = outPut;}
}
客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树。调用解释操作。
/*** @author Shier* CreateTime 2023/5/24 19:31*/
public class ExpressClient {public static void main(String[] args) {Context context = new Context();ArrayList<AbstractExpression> arrayList = new ArrayList<>();arrayList.add(new TerminalExpression());arrayList.add(new NotTerminalExpression());arrayList.add(new TerminalExpression());arrayList.add(new TerminalExpression());for (AbstractExpression expression : arrayList) {expression.interpret(context);}}
}
最终得出的结果:
2、具体例子实现解释器模式
2.1 不使用解释器模式进行翻译
/*** @author Shier* CreateTime 2023/5/24 19:50*/
public class ExpreMain {public static void main(String[] args) {String sentence = "How much does it cost?";String language = "中文";String translatedSentence;if (language.equals("English")) {translatedSentence = translateToEnglish(sentence);} else if (language.equals("Spanish")) {translatedSentence = translateToSpanish(sentence);} else if (language.equals("French")) {translatedSentence = translateToFrench(sentence);} else if (language.equals("中文")) {translatedSentence = translateToChinese(sentence);} else {translatedSentence = "Language not supported";}System.out.println("Translated sentence: " + translatedSentence);}private static String translateToEnglish(String sentence) {// 实现将句子翻译为英语的逻辑return sentence;}private static String translateToChinese(String sentence) {// 实现将句子翻译为英语的逻辑return "要多少钱?";}private static String translateToSpanish(String sentence) {// 实现将句子翻译为西班牙语的逻辑return "¿Cuánto cuesta?";}private static String translateToFrench(String sentence) {// 实现将句子翻译为法语的逻辑return "Combien ça coûte ?";}
}
翻译得到的结果:
2.2 使用解释器模式
具体的实现过程:
抽象表达类:
/*** @author Shier*/
public interface Expression {String interpret(Context context);
}
语言表达符号:
/*** @author Shier*/
public class LanguageExpression implements Expression {private String language;public LanguageExpression(String language) {this.language = language;}@Overridepublic String interpret(Context context) {return context.translate(language);}
}
非语言表达符:
/*** @author Shier*/
public class NonLanguageExpression implements Expression {private Expression firstExpression;private Expression secondExpression;public NonLanguageExpression(Expression firstExpression, Expression secondExpression) {this.firstExpression = firstExpression;this.secondExpression = secondExpression;}@Overridepublic String interpret(Context context) {String firstTranslation = firstExpression.interpret(context);String secondTranslation = secondExpression.interpret(context);return firstTranslation + " " + secondTranslation;}
}
Context:
import java.util.HashMap;
import java.util.Map;public class Context {private Map<String, String> translations;public Context() {translations = new HashMap<>();}public void addTranslation(String language, String translation) {translations.put(language, translation);}public String translate(String language) {return translations.get(language);}
}
客户端:
public class InterpreterExample {public static void main(String[] args) {Context context = new Context();context.addTranslation("English", "Hello");context.addTranslation("French", "Bonjour");context.addTranslation("Spanish", "Hola");Expression englishExpression = new LanguageExpression("English");Expression frenchExpression = new LanguageExpression("French");Expression spanishExpression = new LanguageExpression("Spanish");Expression combinedExpression = new NonLanguageExpression(frenchExpression,spanishExpression);String travelerLanguage = "French";String translatedText = null;if (travelerLanguage.equals("English")) {translatedText = englishExpression.interpret(context);} else if (travelerLanguage.equals("French")) {translatedText = combinedExpression.interpret(context);} else if (travelerLanguage.equals("Spanish")) {translatedText = spanishExpression.interpret(context);}System.out.println("Traveler: " + translatedText);}
}
结果:
2.3 使用解释器模式进行不同的日期格式转换
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;// 抽象表达式接口
interface Expression {LocalDate interpret(String context);
}// 具体表达式类 - 解析“yyyy-MM-dd”格式的日期
class YearMonthDayExpression implements Expression {@Overridepublic LocalDate interpret(String context) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");return LocalDate.parse(context, formatter);}
}// 具体表达式类 - 解析“dd/MM/yyyy”格式的日期
class DayMonthYearExpression implements Expression {@Overridepublic LocalDate interpret(String context) {DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");return LocalDate.parse(context, formatter);}
}// 上下文类
class Context {private Expression expression;public Context(Expression expression) {this.expression = expression;}public LocalDate interpret(String context) {return expression.interpret(context);}
}// 示例
public class Main {public static void main(String[] args) {// 输入日期字符串String dateString = "2023-05-24";// 创建解析器Expression expression = new YearMonthDayExpression();Context context = new Context(expression);// 解析日期LocalDate date = context.interpret(dateString);// 打印解析结果System.out.println("Parsed date: " + date);}
}
到此应该知道解释器模式的用处,我们再来总结一下解释器模式
3、解释器模式总结
3.1 使用场景
- 构建编程语言解释器:解释器模式非常适合构建编程语言解释器,可以将语言的语法规则定义为解释器中的表达式类,并执行对应的操作。
- 规则引擎:解释器模式可以用于实现规则引擎,通过解释器来解析和执行规则,对输入数据进行处理和判断。
- 数学表达式解析:解释器模式可用于解析和计算数学表达式,将表达式表示为抽象语法树,并通过解释器执行相应的操作。
- 查询语言解析:解释器模式可以用于解析和执行查询语言,例如数据库查询语言等。
3.2 解释器模式优点
- 扩展性好:通过增加新的表达式类,可以灵活地扩展解释器的功能。
- 易于实现语法:解释器模式可以通过解析语法树来定义语言的语法规则,使得语法定义清晰明确。
- 易于实现特定领域语言:可以使用解释器模式来实现特定领域语言(Domain-Specific Language, DSL),以满足特定问题领域的需求。
3.3 解释器模式缺点
- 执行效率相对较低:解释器模式通常需要解析和执行语法树,可能会导致较低的执行效率。
- 可能引起类膨胀:如果语法规则非常复杂,可能会导致需要大量的表达式类,从而增加了类的数量,使代码复杂度增加。
实现规则引擎,通过解释器来解析和执行规则,对输入数据进行处理和判断。
3. 数学表达式解析:解释器模式可用于解析和计算数学表达式,将表达式表示为抽象语法树,并通过解释器执行相应的操作。
4. 查询语言解析:解释器模式可以用于解析和执行查询语言,例如数据库查询语言等。
3.2 解释器模式优点
- 扩展性好:通过增加新的表达式类,可以灵活地扩展解释器的功能。
- 易于实现语法:解释器模式可以通过解析语法树来定义语言的语法规则,使得语法定义清晰明确。
- 易于实现特定领域语言:可以使用解释器模式来实现特定领域语言(Domain-Specific Language, DSL),以满足特定问题领域的需求。
3.3 解释器模式缺点
- 执行效率相对较低:解释器模式通常需要解析和执行语法树,可能会导致较低的执行效率。
- 可能引起类膨胀:如果语法规则非常复杂,可能会导致需要大量的表达式类,从而增加了类的数量,使代码复杂度增加。
本文链接:https://my.lmcjl.com/post/8180.html
4 评论