当前位置: 首页 > news >正文

Go和Java实现解释器模式

Go和Java实现解释器模式

下面通过一个四则运算来说明解释器模式的使用。

1、解释器模式

解释器模式提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口

解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。

  • 意图:给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

  • 主要解决:对于一些固定文法构建一个解释句子的解释器。

  • 何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单

    语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

  • 如何解决:构建语法树,定义终结符与非终结符。

  • 关键代码:构建环境类,包含解释器之外的一些全局信息,一般是 HashMap。

  • 应用实例:编译器、运算表达式计算。

  • 优点:1、可扩展性比较好,灵活。 2、增加了新的解释表达式的方式。 3、易于实现简单文法。

  • 缺点:1、可利用场景比较少。 2、对于复杂的文法比较难维护。 3、解释器模式会引起类膨胀。 4、解释器模

    式采用递归调用方法。

  • 使用场景:1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。 2、一些重复出现的问题可

    以用一种简单的语言来进行表达。 3、一个简单语法需要解释的场景。

  • 注意事项:可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。

  • 适用性:

    当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式,而当

    存在当下情况时该模式效果最好:

    该文法简单对于复杂的文法,文法的层次变得庞大而无法管理。

    效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另

    一种形式。

2、Go实现解释器模式

package interpreter// ========== ArithmeticInterpreter ==========
type ArithmeticInterpreter interface {Interpret() int
}
package interpreter// ========== NumInterpreter ==========
type NumInterpreter struct {Value int
}func NewNumInterpreter(value int) *NumInterpreter {return &NumInterpreter{Value: value}
}func (numInterpreter *NumInterpreter) Interpret() int {return numInterpreter.Value
}
package interpreter// ========== AddInterpreter ==========
type AddInterpreter struct {left  ArithmeticInterpreterright ArithmeticInterpreter
}func NewAddInterpreter(left, right ArithmeticInterpreter) *AddInterpreter {return &AddInterpreter{left: left, right: right}
}func (addInterpreter *AddInterpreter) Interpret() int {return addInterpreter.left.Interpret() + addInterpreter.right.Interpret()
}
package interpreter// ========== SubInterpreter ==========
type SubInterpreter struct {left  ArithmeticInterpreterright ArithmeticInterpreter
}func NewSubInterpreter(left, right ArithmeticInterpreter) *SubInterpreter {return &SubInterpreter{left: left, right: right}
}func (subInterpreter *SubInterpreter) Interpret() int {return subInterpreter.left.Interpret() - subInterpreter.right.Interpret()
}
package interpreter// ========== MultiInterpreter ==========
type MultiInterpreter struct {left  ArithmeticInterpreterright ArithmeticInterpreter
}func NewMultiInterpreter(left, right ArithmeticInterpreter) *MultiInterpreter {return &MultiInterpreter{left: left, right: right}
}func (multiInterpreter *MultiInterpreter) Interpret() int {return multiInterpreter.left.Interpret() * multiInterpreter.right.Interpret()
}
package interpreter// ========== DivInterpreter ==========
type DivInterpreter struct {left  ArithmeticInterpreterright ArithmeticInterpreter
}func NewDivInterpreter(left, right ArithmeticInterpreter) *DivInterpreter {return &DivInterpreter{left: left, right: right}
}func (divInterpreter *DivInterpreter) Interpret() int {return divInterpreter.left.Interpret() / divInterpreter.right.Interpret()
}
package interpreterconst (ADD = "+"SUB = "-"MUL = "*"DIV = "/"
)// =========== OperatorUtil ==========
type OperatorUtil struct{}func (OperatorUtil *OperatorUtil) IsOperator(symbol string) bool {return ("+" == symbol || "-" == symbol || "*" == symbol)
}func (operatorUtil *OperatorUtil) GetInterpreter(left, right ArithmeticInterpreter, symbol string) ArithmeticInterpreter {if ADD == symbol {return NewAddInterpreter(left, right)} else if SUB == symbol {return NewSubInterpreter(left, right)} else if MUL == symbol {return NewMultiInterpreter(left, right)} else if DIV == symbol {return NewDivInterpreter(left, right)}return nil
}
package interpreterimport ("fmt""strconv""strings"
)type Calculator struct{}var (operatorUtil = OperatorUtil{}stack        = make([]ArithmeticInterpreter, 0)
)func (calculator *Calculator) Parse(expression string) {elements := strings.Split(expression, " ")var leftExpr, rightExpr ArithmeticInterpreterfor i := 0; i < len(elements); i++ {operator := elements[i]if operatorUtil.IsOperator(operator) {// 出栈leftExpr = stack[len(stack)-1]stack = stack[:len(stack)-1]i++ele, _ := strconv.Atoi(elements[i])rightExpr = NewNumInterpreter(ele)fmt.Printf("出栈: %d 和 %d \n", leftExpr.Interpret(), rightExpr.Interpret())stack = append(stack, operatorUtil.GetInterpreter(leftExpr, rightExpr, operator))fmt.Println("应用运算符: " + operator)} else {ele, _ := strconv.Atoi(elements[i])numInterpreter := NewNumInterpreter(ele)stack = append(stack, numInterpreter)fmt.Printf("入栈: %d \n", numInterpreter.Interpret())}}}func (calculator *Calculator) Result() int {value := stack[len(stack)-1]stack = stack[:len(stack)-1]return value.Interpret()
}
package mainimport ("fmt". "proj/interpreter"
)func main() {calculator := Calculator{}calculator.Parse("10 + 30")fmt.Println("result:", calculator.Result())calculator.Parse("10 + 30 - 20")fmt.Println("result: ", calculator.Result())calculator.Parse("100 * 2 + 400 - 20 + 66")fmt.Println("result:", calculator.Result())
}
# 程序输出
入栈: 10 
出栈: 1030   
应用运算符: +
result: 40
入栈: 10 
出栈: 1030 
应用运算符: +
出栈: 4020 
应用运算符: -
result:  20
入栈: 100 
出栈: 1002 
应用运算符: *
出栈: 200400 
应用运算符: +
出栈: 60020 
应用运算符: -
出栈: 58066 
应用运算符: +
result: 40
入栈: 10 
出栈: 1030 
应用运算符: +
出栈: 4020 
应用运算符: -
result:  20
入栈: 100 
出栈: 1002 
应用运算符: *
出栈: 200400 
应用运算符: +
出栈: 60020 
应用运算符: -
出栈: 58066 
应用运算符: +
result: 646

3、Java实现解释器模式

package com.interpreter;// ========== ArithmeticInterpreter ==========
public interface ArithmeticInterpreter {int interpret();
}
package com.interpreter;// ========== ArithmeticInterpreter ==========
public abstract class Interpreter implements ArithmeticInterpreter{protected ArithmeticInterpreter left;protected ArithmeticInterpreter right;public Interpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {this.left = left;this.right = right;}
}
package com.interpreter;// ========== NumInterpreter ==========
public class NumInterpreter implements ArithmeticInterpreter {private int value;public NumInterpreter(int value) {this.value = value;}@Overridepublic int interpret() {return this.value;}}
package com.interpreter;// ========== AddInterpreter ==========
public class AddInterpreter extends Interpreter {public AddInterpreter() {super(left, right);}@Overridepublic int interpret() {return this.left.interpret() + this.right.interpret();}
}
package com.interpreter;// ========== MultiInterpreter ==========
public class MultiInterpreter extends Interpreter {public MultiInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {super(left, right);}@Overridepublic int interpret() {return this.left.interpret() * this.right.interpret();}
}
package com.interpreter;// ========== SubInterpreter ==========
public class SubInterpreter  extends Interpreter {public SubInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {super(left, right);}@Overridepublic int interpret() {return this.left.interpret() - this.right.interpret();}
}
package com.interpreter;// ========== DivInterpreter ==========
public class DivInterpreter extends Interpreter {public DivInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right) {super(left, right);}@Overridepublic int interpret() {return this.left.interpret() / this.right.interpret();}
}
package com.interpreter;// =========== OperatorUtil ==========
public class OperatorUtil {private final static String ADD = "+";private final static String SUB = "-";private final static String MUL = "*";private final static String DIV = "/";public static boolean isOperator(String symbol) {return ("+".equals(symbol) || "-".equals(symbol) || "*".equals(symbol));}public static Interpreter getInterpreter(ArithmeticInterpreter left, ArithmeticInterpreter right, String symbol) {if (ADD.equals(symbol)) {return new AddInterpreter(left, right);} else if (SUB.equals(symbol)) {return new SubInterpreter(left, right);} else if (MUL.equals(symbol)) {return new MultiInterpreter(left, right);} else if (DIV.equals(symbol)) {return new DivInterpreter(left, right);}return null;}
}
package com.interpreter;import java.util.Stack;// ========== Calculator ==========
public class Calculator {private final Stack<ArithmeticInterpreter> stack = new Stack<>();public void parse(String expression) {String[] elements = expression.split(" ");ArithmeticInterpreter leftExpr, rightExpr;for (int i = 0; i < elements.length; i++) {String operator = elements[i];if (OperatorUtil.isOperator(operator)) {leftExpr = this.stack.pop();rightExpr = new NumInterpreter(Integer.parseInt(elements[++i]));System.out.println("出栈: " + leftExpr.interpret() + " 和 " + rightExpr.interpret());this.stack.push(OperatorUtil.getInterpreter(leftExpr, rightExpr, operator));System.out.println("应用运算符: " + operator);} else {NumInterpreter numInterpreter = new NumInterpreter(Integer.parseInt(elements[i]));this.stack.push(numInterpreter);System.out.println("入栈: " + numInterpreter.interpret());}}}public int result() {return this.stack.pop().interpret();}}
package com.interpreter;public class Test {public static void main(String[] args) {Calculator calculator = new Calculator();calculator.parse("10 + 30");System.out.println("result: " + calculator.result());calculator.parse("10 + 30 - 20");System.out.println("result: " + calculator.result());calculator.parse("100 * 2 + 400 - 20 + 66");System.out.println("result: " + calculator.result());}
}
# 程序输出
入栈: 10
出栈: 1030
应用运算符: +
result: 40
入栈: 10
出栈: 1030
应用运算符: +
出栈: 4020
应用运算符: -
result: 20
入栈: 100
出栈: 1002
应用运算符: *
出栈: 200400
应用运算符: +
出栈: 60020
应用运算符: -
出栈: 58066
应用运算符: +
result: 646
http://www.lryc.cn/news/125160.html

相关文章:

  • 域名配置HTTPS
  • 机械设计cad,ug编程设计,ug模具设计,SolidWorks模具设计
  • 嵌入式开发的学习与未来展望:借助STM32 HAL库开创创新之路
  • WPS-0DAY-20230809的分析和利用复现
  • MongoDB(三十九)
  • InnoDB引擎
  • CSS3中的var()函数
  • opencv图片换背景色
  • JAVA语言:什么是懒加载机制?
  • jupyter默认工作目录的更改
  • Flutter系列文章-Flutter UI进阶
  • Elasticsearch在部署时,对Linux的设置有哪些优化方法?
  • 【网络基础】应用层协议
  • 面试八股文Mysql:(1)事务实现的原理
  • Linux学习之sed多行模式
  • 【刷题笔记8.15】【链表相关】LeetCode:合并两个有序链表、反转链表
  • 神经网络基础-神经网络补充概念-11-向量化逻辑回归
  • openGauss学习笔记-40 openGauss 高级数据管理-锁
  • 勘探开发人工智能技术:机器学习(6)
  • 代理类型中的 HTTP、HTTPS 和 SOCKS 有什么区别?
  • 【STM32RT-Thread零基础入门】 3. PIN设备(GPIO)的使用
  • fiddler抓包工具的用法以及抓取手机报文定位bug
  • spring中时间格式化的两种方式
  • 【设计模式】原型模式
  • Matlab的Filter Designer工具设计二阶低通滤波器
  • 软件测试基础篇——LAMP环境搭建
  • 使用dom4j将xml转为String并去掉所有格式
  • wsl2安装docker引擎(Install Docker Engine on Debian)
  • 百日筑基篇——python爬虫学习(一)
  • 【Spring专题】Spring之底层架构核心概念解析