解释器模式

定义

解释器模式(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实现解释器模式/

设计模式学习-使用go实现解释器模式的更多相关文章

  1. C#设计模式学习笔记:(23)解释器模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8242238.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第十一个模式-- ...

  2. 设计模式之第5章-解释器模式(Java实现)

    设计模式之第5章-解释器模式(Java实现) “开个商店好麻烦,做个收单的系统,发现类的方法好多.”“真是的,不就是简单的四则运算,这都不会!”你说你会啊.来来来,你把以下的方法用代码写出来: a+b ...

  3. 我所理解的设计模式(C++实现)——解释器模式(Interpreter Pattern)

    概述: 未来机器智能化已然成为趋势,现在手机都能听懂英语和普通话,那我大中华几万种方言的被智能化也许也是趋势,我们的方言虽然和普通话相似,但是还是不一样的.这可能需要一个新的语法分析器来帮助我们. 我 ...

  4. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  5. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  6. Java设计模式学习笔记(四) 抽象工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...

  7. [Python设计模式] 第27章 正则表达式——解释器模式

    github地址:https://github.com/cheesezh/python_design_patterns 解释器模式 解释器模式,给定一个语言,定一个它的文法的一种表示,并定一个一个解释 ...

  8. 【设计模式】行为型11解释器模式(Interpreter Pattern)

      解释器模式(Interpreter Pattern) 解释器模式应用场景比较小,也没有固定的DEMO,中心思想就是自定义解释器用来解释固定的对象. 定义:给定一个语言,定义它的文法表示,并定义一个 ...

  9. 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)

    1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e,  要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...

  10. javascript设计模式学习之十三——职责链模式

    一.职责链的定义和使用场景 职责链模式的定义是,职责链模式将一系列可能会处理请求的对象连接成一条链,请求在这些对象之间一次传递,直到遇到一个可以处理它的对象.从而避免请求的发送者和接收者之间的耦合关系 ...

随机推荐

  1. PPT 三维地球动画

    Windows 10 系统自带 画图3D,可以无缝和PPT衔接在一起 百度找一张图片 拖动,包围 到PPT中,插入3D模型(只有 office 365 有) 我这边没有,所以不好继续了 视频地址:(h ...

  2. 发布会回放|Gradio 4.0 正式发布!

    Gradio 的目标是使机器学习模型的演示更容易定制和访问,以满足不同用户的需求.在 4.0 正式版的发布活动上,Hugging Face 的 Gradio 团队介绍了自己为了提高机器学习模型的可访问 ...

  3. EXECL函数

    1 COUNTIF 对比两列数据,有相同的即计为1 找一列空白列,输入=COUNTIF(范围,条件),按回车,然后再点击表格右下角的"+" 就可以拉动持续执行这个函数 2 CONC ...

  4. 关于ABAP索引

    1.什么是索引 如果把数据库表看做一本书,索引就可以看做书的检索目录.目录中包含书中的大小标题(部分字段数据),并且有对应的数据表条目的页码(指针),可以快速的访问数据库表中对应行的所有字段内容 一个 ...

  5. COOIS选择屏幕增强

    一.COOIS生产订单抬头选择屏幕添加筛选条件,并将自定义数据添加到报表 二.修改抬头表AUFK,新增自定义字段 三.选择屏幕新增筛选字段 四.函数模块中,将选择屏幕筛选条件抛到内存 五.BADI:W ...

  6. POJ:1511 Invitation Cards(双向搜索最短路径)

    POJ :1511 http://poj.org/problem?id=1511 思路 求1号点到其他点的最短路 + 其他点到1号点的最短. 结果用long long. 用快读可以加快时间 代码 sp ...

  7. Educational Codeforces Round 100 (Rated for Div. 2) 简单记录

    最近在写Web大作业和期末复习,可能还会有一段时间不会更新blog了 1463A. Dungeon 题意:有3个血量为a,b,c的敌人,现在你每7发子弹能进行一次范围AOE攻击(即一次能集中三人),每 ...

  8. Android 3分钟带你入门开发测试

    作者:Zhu Yifei 作为一名合格的开发人员,基本的开发测试能力必不可少,开发测试分单元测试和UI测试,通过开发测试可以减少开发人员自测时间,提升开发质量.本篇文章可以帮助初级开发人员快速了解开发 ...

  9. C#查找算法1:二分查找

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法.但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列. 原理:将n个元素分成个数大致相同的两半,取 ...

  10. spring boot 整合kafka

    本文为博主原创,未经允许不得转载: 1. 引入spring boot kafka依赖 <dependency> <groupId>org.springframework.kaf ...