极简设计模式-解释器模式

PHP技术
407
0
0
2022-08-04

解释器模式 - Interpreter Pattern

定义

定义一个语言的文法,并且建立一个解释器来解释该语言中的句子。

设计的原则和思想

  1. 解耦的是需要解释的内容和解释文法的方式。
  2. 不变部分是解释文法的方式,变化部分是需要解释的内容。
  3. 核心思想是将语法解析拆分到最小单元,然后按照某种文法规则重新组合。

一句话概括设计模式

用一种类似抽象语法树的表达式去解释一种语言。

终结符和非终结符

终结符

它们是语言的最小组成单位,不能拆分的最小元素。在英文里面终结符是字母。

非终结符

它们都是一个完整的句子,包含一系列终结符或非终结符。在英文里面非终结符是句子或者单词。

结构中包含的角色

  1. AbstractExpression(抽象表达式)
  2. TerminalExpression(终结符表达式)
  3. NonterminalExpression(非终结符表达式)
  4. Context(环境类)

最小可表达代码

// 抽象表达式
abstract class AbstractExpression
{
public abstract function interpret();
}
// 终结符表达式
class FigureTerminalExpression extends AbstractExpression
{
private $figure;
public function __construct($figure)
{
$this->figure = $figure;
}
public function interpret()
{
return $this->figure;
}
}
// 非终结符表达式
class AddNonterminalExpression extends AbstractExpression
{
private $left;
private $right;
public function __construct(AbstractExpression $left, AbstractExpression $right)
{
$this->left = $left;
$this->right = $right;
}
public function interpret()
{
return $this->left->interpret() + $this->right->interpret();
}
}
// 环境类
class Context
{
private $sentence;
public function setSentence(String $sentence)
{
$this->sentence = $sentence;
}
public function calculate()
{
$symbols = [];
$expressions = [];
foreach (explode(' ', $this->sentence) as $char) {
if (is_numeric($char)) {
$expressions[] = new FigureTerminalExpression($char);
} else {
$symbols[] = $char;
}
}
foreach ($symbols as $symbol) {
if ('+' == $symbol) {
$left = array_pop($expressions);
$right = array_pop($expressions);
$expression = (new AddNonterminalExpression($left, $right));
array_unshift($expressions, $expression);
continue;
}
}
return array_pop($expressions)->interpret();
}
}
$context = new Context();
$sentence = '1 + 1';
$context->setSentence($sentence);
var_dump($context->calculate());

优点

  1. 增加了新的解释表达式的方式。
  2. 易于实现简单文法。每一条文法规则都可以表示为一个类,可以方便地实现一个简单的语言。
  3. 容易实现,改变和扩展文法。
  4. 增加新的解释表达式较为方便。增加一个新的终结符表达式或非终结符表达式类即可。

缺点

  1. 可利用场景比较少。
  2. 对于复杂的文法比较难维护。
  3. 解释器模式会引起类膨胀。
  4. 解释器模式中使用了大量的循环和递归调用,执行效率较低。

何时使用

  1. 一些问题可以用简单的语言来表达,并且不关注执行效率的。
  2. 可以将一个需要解释的语言句子表示为一个抽象语法树。

实际应用场景

  1. sql解析。
  2. 正则表达式。
  3. Google Translate 这样的翻译器。