设为首页 加入收藏

TOP

[设计模式]解释器(Interpreter)之大胆向MM示爱吧(一)
2019-09-03 03:21:57 】 浏览:57
Tags:设计模式 解释 Interpreter 大胆 示爱

为方便读者,本文已添加至索引:

写在前面

“我刚写了个小程序,需要你来参与下。”我把MM叫到我的电脑旁,“来把下面这条命令打进去,这是个练习打(Pian)符(ni)号(de)的小程序,看看你能不能全部打正确”。

[*_]_7@1_9@1/(_5@0_3@0)*2/((_4@0)_2$1)_$2^/$1+(_7@0)*2/_$1_6$3/$3_2$3/_3$3_3@0/_5$3

MM诧异地看看我,然后可怜巴巴地坐到屏幕前,对着键盘一个字一个字地敲。她打字超慢的,各种符号都是用两个食指打进去的。她打着打着,说想哭了。我赶忙告诉她,加油,全打正确了有惊喜。

终于,她敲下了回车键。映入眼帘的是:

       _         _
     *   *     *   *     
    *      * *      *    
    *       *       *    
     *             *     
       *         *       
          *   *          
            *            
See Result

她忽然就开心起来,问我这个是怎么回事。我告诉她,“这说明你刚才的命令输对了,电脑按照命令画出了它~。要不再接再厉,试试下面这个更有挑战性的?”

[#*]_@1*5/_(_2@1*2)/$0_9@1*6_(_@1*4)*2_3@1*5/$0_6$0_2$0*2+(_$0)*3/$0_5$0_3$0*3_3@1*8/(_2@0*2)_4@0+$3_3$3*2+(_@0*2)_2$3/$4_4@0_$3_2$3_4@0*3_3$3_2$3/@0*7_5@0*5_4$3_7@0*6

……

是不是读者你也想知道这个会是什么结果了吧?这当然跟我们今天的主题,解释器模式有关啦!会在示例一节展开。

其实,我们平时接触到的解释器模式相关的实际例子并不太多,最常见的莫过于正则表达式了。它通过规定一系列的文法规则,并给予了相关的解释操作,从而成为处理字符串的通用强大的工具。首先我们了解下解释器模式的相关技术要点,然后在示例部分,我们将解释上文中所出现的莫名的式子。

要点梳理

  • 目的分类
    • 类行为型模式
  • 范围准则
    • 类(该模式处理类和子类之间的关系,这些关系通过继承建立,是静态的,在编译时刻便确定下来了)
  • 主要功能
    • 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
  • 适用情况
    • 当有一个语言需要解释执行, 并且我们可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。当存在以下情况时,效果最好:
      • 该文法简单。对于复杂的文法, 文法的类层次变得庞大而无法管理
      • 效率不是一个关键问题。最高效的解释器通常不是通过直接解释语法分析树实现。
  • 参与部分
    • AbstractExpression(抽象表达式):声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享
    • TerminalExpression(终结符表达式):实现与文法中的终结符相关联的解释操作,一个句子中的每个终结符需要该类的一个实例
    • NonterminalExpression(非终结符表达式):为文法中的非终结符实现解释操作。解释时,一般要递归调用它所维护的AbstractExpression类型对象的解释操作
    • Context(上下文):包含解释器之外的一些全局信息
    • Client(用户):构建(或被给定) 表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由TerminalExpression和NonterminalExpression的实例装配而成。
  • 协作过程
    • Client构建一个句子,它是TerminalExpression和NonterminalExpression的实例的一个抽象语法树,然后初始化上下文,并调用解释操作。
    • 每一非终结符表达式节点定义相应子表达式的解释操作。
    • 每一节点的解释操作用上下文来存储和访问解释器的状态。
  • UML图

示例分析 - 字符画解释器

为了让MM不明觉厉,我想到了通过简单的解释器来实现,从字符串到一个字符画的转换过程。我觉得利用stringstream流可以方便地构建一个字符画,因此,我们首先确定我们实现这个模式的上下文(Context)就是stringstream对象。然后我们定义一些具体的字符操作表达式。它们是可以画出字符画的一些基本操作:

TerminalExpression:

  • Constant:常量表达式。它也是终结符表达式。它的解释操作就是将一个固定的string插入到Context流中。

NonterminalExpression:

  • RepeatExpression:重复表达式。它是非终结符表达式。它的解释操作就是使一个Expression重复N次。
  • AddExpression:加法表达式。非终结符表达式。它的解释操作是使两个Expression拼接在一起。
  • ReverseExpression:反转表达式。非终结符表达式。它的解释操作是使一个Expression逆序。

可以看到这几个表达式是可以构成抽象语法树的。让我们看看代码:

 1 #ifndef EXPRESSION_H_INCLUDED
 2 #define EXPRESSION_H_INCLUDED
 3 
 4 #include <string>
 5 #include <sstream>
 6 
 7 using namespace std;
 8 
 9 // ... Abstract Class ...
10 class Expression {
11 public:
12     Expression() {}
13     virtual ~Expression() {}
14 
15     virtual void eva l(stringstream&) = 0;
16 };
17 
18 // ... RepeatExpression Class ...
19 class RepeatExpression : public Expression {
20 public:
21     RepeatExpression(Expression*, int);
22 
23     void eva l(stringstream&);
24 private:
25     Expression* _oper;
26     int         _mNum;
27 };
28 
29 // ... AddExpression Class ...
30 class AddExpression : public Expression {
31 public:
32     AddExpression(Expression*, Expression*);
33 
34     void eva l(stringstream&);
35 private:
36     Expression* _oper1;
37     Expression* _oper2;
38 };
39 
40 // ... ReverseExpression Class ...
41 class ReverseExpression : public Expression {
42 public:
43     ReverseExpression(Expression*);
44 
45     void eva l(stringstream&);
46 private:
47     Expression* _oper;
48 };
49 
50 //
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇以SqlHelper为例论面向对象中封装.. 下一篇工厂方法模式与抽象工厂模式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目