23种设计模式(C++)之 解释器(Interpreter)模式

23种设计模式(C++)之 解释器(Interpreter)模式

23种设计模式(C++)之 解释器(Interpreter)模式

意图

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

适用性

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

  • 该文法简单。对于复杂的文法,文法的类层次变得庞大而无法管理。(此时语法分析程序生成器这样的工具是更好的选择,它们无需构建抽象语法树即可解释表达式,这样可以节省空间和时间)
  • 效率不是一个关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将他们转换成另外一种形式。(例如,正则表达式通常被转换成状态机)

场景

比如查看指定产品是否存在,查看句子是否合理,四则运算,编译器等等。

角色

  • AbstractExpression
    • 声明一个抽象的解释操作,这个接口为抽象语法树中所有节点所共享
  • TerminalExpression (终结符表达式)
    • 实现与文法中的终结符相关联的解释操作
    • 一个句子中的每个终结符需要该类的一个实例
  • NonterminalExpression (非终结符表达式)
    • 对文法中的每一条规则R ::=R1R2…Rn都需要一个非终结符表达式
    • 为从R1 到Rn的每个符号都维护一个AbstractExpression类型的实例变量
    • 为文法中的非终结符实现解释操作。(解释一般要递归地调用表示R1到Rn的那些对象的解释操作)
  • Context(上下文)
    • 包含解释器之外的一些全局信息
  • Client
    • 构建表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。
    • 调用解释操作

实例

以解释“颜色+车”为例:

  1. 创建表达式接口
class Express
{
public:
	virtual bool interpret(string info) = 0;
};
  1. 创建终结符表达式
class TerminalExpress : public Express
{
private:
	vector<string > names;
public:
	TerminalExpress(vector<string > names)
	{
		this->names = names;
	}
	bool interpret(string info)
	{
		vector<string >::iterator it;
		for (it = this->names.begin(); it != this->names.end();) 
		{
			if (info.find(*it) == string::npos)
			{
				++it;
			}
			else 
			{
				return true;
			}
		}
		return false;
	}
};
  1. 创建非终结符表达式
class AndTerminalExpress : public Express
{
private:
	Express* express1;
	Express* express2;
public:
	AndTerminalExpress(Express* express1, Express* express2)
	{
		this->express1 = express1;
		this->express2 = express2;
	}
	bool interpret(string info)
	{
		return this->express1->interpret(info) && this->express2->interpret(info);
	}
};
  1. 创建上下文类
class Context
{
private:
	Express* andExpress;
public:
	Context()
	{
		vector<string> color = { "blue", "black", "white" };
		vector<string> car = { "electricCar","oilCar" };
		Express* colorExpress = new TerminalExpress(color);
		Express* carExpress = new TerminalExpress(car);
		this->andExpress = new AndTerminalExpress(colorExpress, carExpress);
	}
	void checkIfExist(string info)
	{
		if (this->andExpress->interpret(info))
		{
			cout << info + " exists." << endl;
		}
		else
		{
			cout << "Sorry, " + info + " doesn't exist." << endl;
		}
	}
};
  1. 创建客户类
int main()
{
	Context* context = new Context();
	context->checkIfExist("blue oilCar");
	context->checkIfExist("yellow oilCar");
}
  1. 结果
blue oilCar exists.
Sorry, yellow oilCar doesn't exist.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值