解释器模式-类行为型模式

意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器适用该标识来解释语言中的句子。

动机:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

例如:搜索匹配一个模式的字符串是一个常见的问题。正则表达式是描述字符串模式的一种标准语言。与其为每一个模式都构造一个特定的算法,不如使用一种通用的搜索算法来解释执行一个正则表达式,该正则表达式定义了待匹配字符串的集合。

解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。即上面例子,本设计模式描述如何为正则表达式定义一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。

适用性

当一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象的语树时,可使用解释器模式。当存在以下情况时,该模式效果最好:

1 该文法简单。对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式,这样可以节省空间而且还能节省时间。

2 效率不是一个关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是先将它们转换成另一种形式。例如正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍然有用。

结构


参与者:

AbstractExpression(抽象表达式)

声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。

TerminalExpression(终结符表达式)

实现与文法中的终结符相关联的解释操作。一个句子中的每个终结符需要该类的一个实例。

NonterminalExpression(非终结符表达式)

对文法中的每一条规则 R::=R1R2…Rn都需要一个NonterminalExpression类。

为从R1Rn的每个符号都维护一个AbstractExpression类型的实例变量。

为文法中的非终结符实现解释操作。解释一般要递归地调用表示R1Rn的那些对象的解释操作。

Context(上下文):包含解释器外的一些全局信息

Client(客户):

构建表示该文发定义的语句中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpressionTerminalExpression的实例装配而成。

调用解释操作。

协作:

Client构建一个句子,它是NonterminalExpressionTerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作。

每一个非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础。

每一节点的解释操作用上下文来存储和访问解释器的状态。

效果:

有如下优点和不足:

1 易于改变和扩展文法;2 也易于实现文法  3 复杂的文法难以维护 4 增加了新的解释表达式的方式。

实现:

1 创建抽象语法树 2 定义解释操作 3 Flyweight模式共享终结符

已知应用:解释器模式在OO语言中的编译器中得到了广泛的应用。

相关模式:

Composite:抽象语法树是一个复合模式的实例

Flyweight模式:说明了如何在抽象语法树中共享终结符

Iterator:解释器可用一个迭代器遍历该结构

Visitor:可用来在一个类中维护抽象语法树中的各节点的行为


代码(有问题,Context类和Constant类实现有些问题-_-):

//解释器模式

#include <iostream>
#include <cstring>
using namespace std;

class Context;
//为所有定义一个布尔表达式的类定义一个接口 
class BooleanExp {
public:
    BooleanExp() {}
    virtual ~BooleanExp() {}
    
    virtual bool Evaluate(Context&) = 0;
    virtual BooleanExp* Replace(const char*, BooleanExp&) = 0;
    virtual BooleanExp* Copy() const = 0; 
};

class VariableExp;
//定义从变量到布尔值的一个映射,布尔值用true和false表示 
class Context
{
public:
    bool Lookup(const char* name) const
    {
        return true;
    }
      
    void Assign(VariableExp* var, bool b)
    {
        
    }
};

//表示一个有名变量 
class VariableExp : public BooleanExp
{
public:
    //将变量的名字作为参数 
    VariableExp(const char* name, bool b = true) : boolValue(b)
    {
        _name = new char[strlen(name)+1];
        strcpy(_name, name);
    }
    
    virtual ~VariableExp()
    {
        delete [] _name;
    }
    
    //求一个变量的值,返回它在当前上下文中的值 
    bool Evaluate(Context& aContext)
    {
        return aContext.Lookup(_name);
    }
    
    //用表达式替换一个变量,检查该替换变量是否就是本对象代表的变量 
    BooleanExp* Replace(const char* name, BooleanExp& exp)
    {
        if (strcmp(name, _name) == 0)
            return exp.Copy();
        else
            return new VariableExp(name);
    }
    
    //拷贝一个变量返回一个新的VariableExp 
    BooleanExp* Copy() const
    {
        return new VariableExp(_name);
    }
private:
    char* _name;
};

//AndExp表示由两个布尔表达式与操作得到的表达式
class AndExp : public BooleanExp
{
public:
    AndExp(BooleanExp* op1, BooleanExp* op2)
       : _operand1(op1), _operand2(op2)
    {
    }
    
    //一个AndExp的值是求它的两个操作数的值的逻辑“与” 
    bool Evaluate(Context& aContext)
    {
        return _operand1->Evaluate(aContext) &&
               _operand2->Evaluate(aContext);
    }
    
    //Copy和Replace操作递归调用它的操作数的Copy和Replace操作
    BooleanExp* Copy() const
    {
        return new AndExp(_operand1->Copy(), _operand2->Copy());
    } 
    
    BooleanExp* Replace(const char* name, BooleanExp& exp)
    {
        return new AndExp(
            _operand1->Replace(name, exp), _operand2->Replace(name, exp)); 
    }
private:
    BooleanExp* _operand1;
    BooleanExp* _operand2;
}; 

//OrExp表示由两个布尔表达式或操作得到的表达式
class OrExp : public BooleanExp
{
public:
    OrExp(BooleanExp* op1, BooleanExp* op2)
       : _operand1(op1), _operand2(op2)
    {
    }
    
    //一个OrExp的值是求它的两个操作数的值的逻辑"或” 
    bool Evaluate(Context& aContext)
    {
        return _operand1->Evaluate(aContext) &&
               _operand2->Evaluate(aContext);
    }
    
    //Copy和Replace操作递归调用它的操作数的Copy和Replace操作
    BooleanExp* Copy() const
    {
        return new OrExp(_operand1->Copy(), _operand2->Copy());
    } 
    
    BooleanExp* Replace(const char* name, BooleanExp& exp)
    {
        return new OrExp(
            _operand1->Replace(name, exp), _operand2->Replace(name, exp)); 
    }
private:
    BooleanExp* _operand1;
    BooleanExp* _operand2;
}; 

//NotExp表示一个表达式非操作得到的结果 
class NotExp : public BooleanExp
{
public:
    NotExp(BooleanExp* op) : _operand(op)
    {
    }
    
    //一个NotExp的值是求它的两个操作数的值的逻辑“与” 
    bool Evaluate(Context& aContext)
    {
        return ~(_operand->Evaluate(aContext));
    }
    
    //Copy和Replace操作递归调用它的操作数的Copy和Replace操作
    BooleanExp* Copy() const
    {
        return new NotExp(_operand->Copy());
    } 
    
    BooleanExp* Replace(const char* name, BooleanExp& exp)
    {
        return new NotExp(_operand->Replace(name, exp)); 
    }
private:
    BooleanExp* _operand;
};

//表示布尔常量 
class Constant : public BooleanExp
{
public:
    Constant(bool b) : cc(b)
    {}
    
    bool Evaluate(Context& aContext)
    {
        return cc;
    }
    
    //Copy和Replace操作递归调用它的操作数的Copy和Replace操作
    BooleanExp* Copy() const
    {
        return new Constant(cc);
    } 
    
    BooleanExp* Replace(const char* name, BooleanExp& exp)
    {
        return new Constant(true); 
    }
private:
    bool cc;
};
 
int main()
{
    //求解bool表达式:(true and x) or (y and (not x)),x,y被赋值为true或false 
    BooleanExp* expression;
    Context context;
    
    VariableExp* x = new VariableExp("X");
    VariableExp* y = new VariableExp("Y");
    
    expression = new OrExp(
        new AndExp(new Constant(true), x),
        new AndExp(y, new NotExp(x))
    );
    
    context.Assign(x, false);
    context.Assign(y, true);
    
    bool result = expression->Evaluate(context); 
    cout << result << endl;

    //替换y表达式    
    VariableExp* z = new VariableExp("Z");
    NotExp not_z(z);
    
    BooleanExp* replacement = expression->Replace("Y", not_z);
    context.Assign(z, true);
    cout << replacement->Evaluate(context); << endl;

    system("pause");
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值