解释器模式
解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示。并定义一个解释器,这个解释器使用该表示来解释语言中的句子。简单来说,就是为了解释一种语言,而为语言创建的解释器。
适用场景
某个特定类型问题发生频率足够高(例如日志解析,计算器)
优点
语法由很多类表示,容易改变以及扩展此"语言"
缺点
当语法规则数目太多时,增加了系统复杂度
在实际的开发工作中,解释器一般会由编程语言本身提供的库来实现,我们一遍不需要太多关心。但是我还是引入一种应用场景来学习一下,就是一个加减计算器。
下面从 golang-design-pattern引入的一个例子。
Golang Demo
package interpreter
import (
"strconv"
"strings"
)
type Node interface {
Interpret() int
}
type ValNode struct {
val int
}
func (n *ValNode) Interpret() int {
return n.val
}
type AddNode struct {
left, right Node
}
func (n *AddNode) Interpret() int {
return n.left.Interpret() + n.right.Interpret()
}
type MinNode struct {
left, right Node
}
func (n *MinNode) Interpret() int {
return n.left.Interpret() - n.right.Interpret()
}
type Parser struct {
exp []string
index int
prev Node
}
func (p *Parser) Parse(exp string) {
p.exp = strings.Split(exp, " ")
for {
if p.index >= len(p.exp) {
return
}
switch p.exp[p.index] {
case "+":
p.prev = p.newAddNode()
case "-":
p.prev = p.newMinNode()
default:
p.prev = p.newValNode()
}
}
}
func (p *Parser) newAddNode() Node {
p.index++
return &AddNode{
left: p.prev,
right: p.newValNode(),
}
}
func (p *Parser) newMinNode() Node {
p.index++
return &MinNode{
left: p.prev,
right: p.newValNode(),
}
}
func (p *Parser) newValNode() Node {
v, _ := strconv.Atoi(p.exp[p.index])
p.index++
return &ValNode{
val: v,
}
}
func (p *Parser) Result() Node {
return p.prev
}
package interpreter
import "testing"
func TestInterpreter(t *testing.T) {
p := &Parser{}
p.Parse("1 + 2 + 3 - 4 + 5 - 6")
res := p.Result().Interpret()
expect := 1
if res != expect {
t.Fatalf("expect %d got %d", expect, res)
}
}
Java Demo
package tech.selinux.design.pattern.behavioral.interpreter;
public interface Node {
int interpret();
}
package tech.selinux.design.pattern.behavioral.interpreter;
public class AddNode implements Node {
Node left;
Node right;
public AddNode(Node left, Node right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return this.left.interpret() + this.right.interpret();
}
}
package tech.selinux.design.pattern.behavioral.interpreter;
public class MinNode implements Node {
Node left;
Node right;
public MinNode(Node left, Node right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return this.left.interpret() - this.right.interpret();
}
}
package tech.selinux.design.pattern.behavioral.interpreter;
public class ValNode implements Node {
int val;
public ValNode(int val) {
this.val = val;
}
@Override
public int interpret() {
return this.val;
}
}
package tech.selinux.design.pattern.behavioral.interpreter;
import org.apache.commons.lang3.StringUtils;
public class Parser {
String[] exp;
int index;
Node prev;
public void parse(String expression) {
exp = StringUtils.split(expression);
while (true) {
if (index >= exp.length) {
return;
}
System.out.println(exp[index]);
switch (exp[index].charAt(0)) {
case '+':
index++;
prev = new AddNode(prev, newValNode());
break;
case '-':
index++;
prev = new MinNode(prev, newValNode());
break;
default:
prev = newValNode();
break;
}
}
}
public Node newValNode() {
int v = Integer.parseInt(exp[index]);
index++;
return new ValNode(v);
}
public Node result() {
return prev;
}
}
package tech.selinux.design.pattern.behavioral.interpreter;
public class Test {
public static void main(String[] args) {
Parser parser = new Parser();
parser.parse("1 + 2 + 3 - 4 + 5 - 6");
int res = parser.result().interpret();
System.out.println(res);
}
}
Last updated