随笔 - 308  文章 - 0  评论 - 84  阅读 - 75万

设计模式学习-使用go实现解释器模式

解释器模式

定义

解释器模式(interpreter):给定一种语言,定义它的文法的一种表示,并定一个解释器,这个解释器使用该表示来解释语言中的句子。

解释器模式的意义在于,它分离多种复杂功能的实现,每个功能只需关注自身的解释。

对于调用者不用关心内部的解释器的工作,只需要用简单的方式组合命令就可以。

优点

1、可扩展性比较好,灵活;

2、增加了新的解释表达式的方式;

3、易于实现简单文法。

缺点

1、可利用场景比较少;

2、对于复杂的文法比较难维护;

3、解释器模式会引起类膨胀。

适用范围

解释器模式的代码实现比较灵活,没有固定的模板。我们前面也说过,应用设计模式主要是应对代码的复杂性,实际上,解释器模式也不例外。它的代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分成一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

代码实现

这里简单实现了一个加减的运算器,我们对每种运算定义对应的方法,避免所有的运算操作放到一个函数中,这就体现了解释器模式的核心思想,将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。

type Expression interface {
	Interpret() int
}

type NumberExpression struct {
	val int
}

func (n *NumberExpression) Interpret() int {
	return n.val
}

type AdditionExpression struct {
	left, right Expression
}

func (n *AdditionExpression) Interpret() int {
	return n.left.Interpret() + n.right.Interpret()
}

type SubtractionExpression struct {
	left, right Expression
}

func (n *SubtractionExpression) Interpret() int {
	return n.left.Interpret() - n.right.Interpret()
}

type Parser struct {
	exp   []string
	index int
	prev  Expression
}

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.newAdditionExpression()
		case "-":
			p.prev = p.newSubtractionExpression()
		default:
			p.prev = p.newNumberExpression()
		}
	}
}

func (p *Parser) newAdditionExpression() Expression {
	p.index++
	return &AdditionExpression{
		left:  p.prev,
		right: p.newNumberExpression(),
	}
}

func (p *Parser) newSubtractionExpression() Expression {
	p.index++
	return &SubtractionExpression{
		left:  p.prev,
		right: p.newNumberExpression(),
	}
}

func (p *Parser) newNumberExpression() Expression {
	v, _ := strconv.Atoi(p.exp[p.index])
	p.index++
	return &NumberExpression{
		val: v,
	}
}

func (p *Parser) Result() Expression {
	return p.prev
}

测试代码

func TestInterpreter(t *testing.T) {
	p := &Parser{}
	p.Parse("1 + 3 + 3 + 3 + 3")
	res := p.Result().Interpret()
	expect := 13
	if res != expect {
		t.Fatalf("expect %d got %d", expect, res)
	}
	t.Log(res)
}

参考

【文中代码】https://github.com/boilingfrog/design-pattern-learning/tree/master/解释器模式
【大话设计模式】https://book.douban.com/subject/2334288/
【极客时间】https://time.geekbang.org/column/intro/100039001
【设计模式】https://github.com/senghoo/golang-design-pattern
【解释器模式】https://boilingfrog.github.io/2021/11/30/使用go实现解释器模式/

posted on   ZhanLi  阅读(194)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示