解释器模式 Interpreter Pattern

未匹配的标注

定义

定义一个语言的文法,并且建立一个解释器来解释该语言中的句子。
解释器模式的应用有查询对象(Query Object),用于表示SQL查询。

设计的原则和思想

  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 这样的翻译器。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 0
发起讨论 只看当前版本


暂无话题~