设计模式之解释器模式(C++实现)

更多设计模式参看: 设计模式之模式概述(模式汇总)(C++实现)

介绍

解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。实际上,这里的“语言”不仅仅指我们平时说的中、英、日、法等各种语言。从广义上来讲,只要是能承载信息的载体,都可以称之为“语言”,比如,古代的结绳记事、盲文、哑语、摩斯密码等。

意图:

解释器模式(Interpreter Pattern): 定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

解决问题:

如何对信息载体(语言等)进行解释的问题

实现概述:

每个文法规则的语言实例都可以表示为一个抽象语法树,即每一条具体的语句都可以用抽象语法树来表示。终结符表达式类的实例作为树的叶子节点,而非终结符表达式类的实例作为非叶子节点,它们可以将终结符表达式类的实例以及包含终结符和非终结符实例的子表达式作为其子节点。抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符类和非终结符类。参见Redy语法分析--抽象语法树简介

要点:

构建语法树,定义终结符与非终结符。

应用场景:

  • 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
  • 一些重复出现的问题可以用一种简单的语言进行表达;
  • 一个语言的文法较为简单;
  • 不考虑执行效率的问题时可以使用解释器模式。

优点:

  • 易于改变和扩展文法,在解释器中使用类表示语言的文法规则,可以通过继承等机制类改变或扩展文法;
  • 每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言;
  • 如果要增加新的解释表达式,只需增加一个新的终结符表达式或非终结符表达式类,无需修改原有代码,符合开闭原则。

缺点:

  • 对于复杂文法难以维护。由于在解释器模式中每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会大量增加,导致系统难以管理和维护;
  • 执行效率低,因为解释器模式中有大量循环和递归调用

模式结构

角色

  • AbstractExpression(抽象表达式): 声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类。
  • TerminalExpression(终结符表达式): 终结符是文法规则的组成元素中最基本的语言单位,不能再分解。 实现了与文法规则中终结符相关的解释操作,句子中的每一个终结符都是该类的一个实例。
  • NonterminalExpression(非终结符表达式): 实现了文法中非终结符的解释操作,非终结符表达式中可以包含终结符表达式,也可以继续包含非终结符表达式,因此其解释操作一般通过递归的方式来完成。
  • Context(环境类): 环境类又称为上下文类,存储解释器之外的一些全局信息,通常它可以临时存储需要解释的语句。

类图

在这里插入图片描述

代码示例

解释机器人控制指令(网上很多都用的这个例子ヾ(。 ̄□ ̄)ツ゜゜゜)

说明:
机器人控制程序中包含一些简单的英文控制指令,每一个指令对应一个表达式(expression),
该表达式可以是简单表达式也可以是复合表达式,每一个简单表达式由移动方向(direction),移动方式(action)和移动距离(distance)三部分组成,
其中移动方向包括上(up)、下(down)、左(left)、右(right);
移动方式包括移动(move)和快速移动(run);
移动距离为一个正整数。
两个表达式之间可以通过与(and)连接,形成复合(composite)表达式。
文法规则:
expression = direction + action + distance 或 composite //表达式
composite = expression + 'and' + expression //复合表达式
direction = 'up' 或 'down' 或 'left' 或 'right' //移动方向
action = 'move' 或 'run' //移动方式
distance = an integer //移动距离
终结符(也称为终结符表达式):direction、action 和 distance,它们是语言的最小组成单位,不能再进行拆分;
非终结符(也称为非终结符表达式),expression 和 composite,它们都是一个完整的句子,包含一系列终结符或非终结符。

AbstractExpression(抽象表达式): AbstractNode

TerminalExpression(终结符表达式):DirectionNode、ActionNode、DistanceNode

NonterminalExpression(非终结符表达式):AndNode 、SentenceNode

Context(环境类):Handler (指令处理类工具类)

GitHub

InterpreterPattern

AbstractExpression(抽象表达式)

/// AbstractExpression(抽象表达式): AbstractNode
class AbstractNode {
   
public:
    virtual ~AbstractNode() = default;
    virtual std::string interpret() = 0;
protected:
    AbstractNode() = default;
};

TerminalExpression(终结符表达式)

/// TerminalExpression(终结符表达式):DrectionNode 、ActionNode、DistanceNode
//方向解释:终结符表达式
class DirectionNode : public AbstractNode {
   
public:
    explicit DirectionNode(const std::string &direction) {
   
        this->direction = direction;
        std::cout << "DirectionNode, Hello. Direction = " << this->direction << std::endl;
    }
    ~DirectionNode() override {
   
        std::cout << "DirectionNode, Bye. Direction = " << this->direction << std::endl;
    }

    //方向表达式的解释操作
    std::string interpret() override {
   
        /// 注 这里未处理 大写 字母, 演示模式 默认 全小写
        if (direction == "up") {
   
            return "向上";
        } else if (direction == "down") {
   
            return "向下";
        } else if (direction == "left") {
   
            return "向左";
        } else if (direction == 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值