设计模式(Java)—Interpreter模式

这篇博客介绍了Interpreter模式,通过一个控制无线玩具车的迷你语言为例,详细阐述了如何设计并使用解释器模式。内容包括迷你语言的命令、语法解析、递归定义以及示例程序的实现。此外,还提出了扩展功能,如运行迷你程序、GUI显示及使用Facade模式等。
摘要由CSDN通过智能技术生成

在Interpreter模式中,程序要解决的问题会被用非常简单的“迷你语言”表述出来,即用“迷你语言”编写的“迷你程序”把具体问题表述出来。迷你程序是无法单独工作的,我们还需要用Java语言编写一个负责“翻译”的程序。翻译程序会理解迷你语言,并解释和运行迷你程序。这段翻译程序也称为解释器。这样,当需要解决的问题发生变化时,不需要修改Java语言程序,只需要修改迷你语言程序即可应对。
使用Java语言编程时,需要修改代码,但是,在使用Interpreter模式后,我们就无需修改Java程序,只需修改迷你语言编写的迷你程序即可。
在这里插入图片描述

迷你语言
此次迷你语言的用途是控制无线玩具车。虽说是玩具车,其实能做的事情不过以下3种。

  • 前进1米(go)
  • 右转(right)
  • 左转(left)
  • 重复(repeat)
    以上就是可以向玩具车发送的命令,go是前进1米后停止的命令;right是原地向右转的命令,left是原地向左转的命令。在实际操作时,是不能完全没有偏差地原地转弯的,为了使问题简单化,我们这里并不会改变玩具车的位置,而是像将其放在旋转桌子上一样,让他转个方向。
    以上命令组合起来就是可以控制无线玩具车的迷你语言了。

控制无线玩具车的迷你语言
在这里插入图片描述

迷你语言程序示例
下面我们来看一段用迷你语言编写的迷你程序。下面这条语句可以控制无线玩具车前进(之后停止)。
program go end
为了便于大家看出语句的开头和结尾,我们在语句前后分别加上了program和end关键字。这个迷你程序的运行结果如下。

program go end的运行结果
在这里插入图片描述

接下来是一段让无限玩具车先前进一米,接着让它右转两次再返回的程序。
program go right right go end
再接下来的这段程序是让无线玩具车按照正方形路径行进,其运行结果如下所示。
program go right go right go right go right end…(A)
program go right go right go right go right end的运行结果
在这里插入图片描述

(A)程序的最后(即end之前)之所以加上了right,是因为当无线玩具车回到起点后,我们希望它的方向与出发时相同,在(A)程序中,重复出现了4次go right。这样,我们可以使用repeat…end语句来实现下面的(B)程序(为了能够编写出这段程序,我们需要定义迷你语言的语法),其运行结果如图所示。
在这里插入图片描述
program repeat 4 go right end end …(B)

在(B)程序的最后出现了两个end,其中第一个(左边)end表示repeat的结束,第二个(右边)end表示program的结束,也就是说,程序的结构如下:
在这里插入图片描述

再如:
program repeat 4 repeat 3 go right go left end right end end
现在玩具车会按照如下图所示的锯齿形状路线前进。
在这里插入图片描述

这段程序可分解如下形式:
在这里插入图片描述

内侧的循环语句是go right go left,它是一条让无线玩具车“前进后右转,前进后左转”的命令。该命令会重复3次。这样,玩具车就会向右沿着锯齿形路线行进,接着,退至外侧循环看,玩具车会连续4次“沿着锯齿形路线进行一次后,右转一次”。这样,最终行进路线就变成了一个锯齿样的菱形。

迷你语言的语法
在这里插入图片描述
上图展示了迷你语言的语法。这里使用的描述方法是BNF的一个变种,BNF经常被用于描述算法。

<program>::=program <command list>
首先我们定义了程序<program>,即“所谓<program>,是指program关键字后面跟着的命令列表<command list>”,“::=”的左边表示定义的名字,右边表示定义的内容。

<command list> ::=<command>* end
接着,我们定义了命令列表<command list>,即“所谓<command list>,是指重复0次以上<command>后,接着一个end关键字”,“*”表示前面的内容循环0次以上。

<command> ::=<repeat command> | <primitive command>
现在,我们来定义<command>,即“所谓<command>,是指<repeat command>或<primitive command>”。

<repeat command>::= repeat <number><command list>
接下来,我们定义循环命令,即“所谓<repeat command>,是指repeat关键字后面跟着循环次数<number>”和要循环的命令列表<command list>。其中<command list>在之前已经定义过了,而在定义命令列表的时候使用了<command>,在定义<command>的时候又使用了<command>,而在定义<repeat command>的时候又使用了<command list>,像这样,在定义某个东西时,他自身又出现在了定义的内容中,我们称这种定义为递归定义。

<primitive command>::= go | right | left
这是基本命令<primitive command>的定义,即“所谓<primitive command>是指go或者right或者left”。

终结符表达式与非终结符表达式
前面讲到的想<primitive command>这样的不会进一步展开的表达式被成为“终结符表达式”。与之相对的是,像<command>和<repeat command>这样的需要被进一步展开的表达式被成为“非终结符表达式”。

示例程序
示例程序实现了一个迷你程序的语法解析器。
在之前学习迷你程序的相关内容时,我们分别学习了迷你程序的各个语法部分。像这样将迷你程序当作普通字符分解,然后看看各个部分分别是什么结构的过程,就是语法解析。

例如有迷你程序
program repeat 4 go right end end
将这段迷你程序推导成为下图那样的结构(语法树)的处理,就是语法解析。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值