设计模式之解释器模式-不解释,自己看!
解释器模式
一、解释器模式的概念
解释器模式属于行为型模式,它提供一个文法表达式处理接口,该接口解释一个特定的上下文,它用编译语言的方式来分析应用中的实例对象。
二、解释器模式使用场景
1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
2、一些重复出现的问题可以用一种简单的语言来进行表达。
3、一个简单语法需要解释的场景。
三、解释器模式构建方法
1、环境类(Context)
环境类又称为上下文类,它用于存储解释器之外的一些全局信息和需要解释的语句。
2、抽象表达式类(AbstractExpression)
在抽象表达式中声明了抽象的解释操作,它是所有终结符表达式和非终结符表达式的公共父类,定义了终结符表达式和非终结符表达式的公共实现接口。
3、终结符表达式类(TerminalExpression)
终结符表达式是抽象表达式的子类,它实现了与文法中的终结符相关联的解释操作,在句子中的每一个终结符都是该类的一个实例。
4、非终结符表达式类(NonterminalExpression)
非终结符表达式也是抽象表达式的子类,它实现了文法中非终结符的解释操作,在非终结符表达式中可以包含终结符表达式和非终结符表达式,其解释操作一般通过递归的方式完成。
四、解释器模式的示例
// InterpreterPattern.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <string>
#define DELETE_PTR(p) {if(p!=nullptr){delete (p); (p)=nullptr;}}
using namespace std;
// 抽象表达式类
class AbstarctExpression
{
public:
virtual int interpreter() = 0;
};
// 非终结符表达式类
class SymbolExpression : public AbstarctExpression
{
public:
SymbolExpression(string numStr)
{
m_numStr = numStr;
}
int interpreter()
{
if (m_numStr.empty())
{
return -1;
}
return atoi(m_numStr.c_str());
}
private:
string m_numStr;
};
// 终结符表达式类-加法运算
class PlusExpression : public AbstarctExpression
{
public:
PlusExpression(int firstNum, int secondNum)
{
m_firstNum = firstNum;
m_secondNum = secondNum;
}
int interpreter()
{
return (m_firstNum + m_secondNum);
}
private:
int m_firstNum;
int m_secondNum;
};
// 终结符表达式类-减法运算
class MinusExpression : public AbstarctExpression
{
public:
MinusExpression(int firstNum, int secondNum)
{
m_firstNum = firstNum;
m_secondNum = secondNum;
}
int interpreter()
{
return (m_firstNum - m_secondNum);
}
private:
int m_firstNum;
int m_secondNum;
};
// 终结符表达式类-乘法运算
class MultiExpression : public AbstarctExpression
{
public:
MultiExpression(int firstNum, int secondNum)
{
m_firstNum = firstNum;
m_secondNum = secondNum;
}
int interpreter()
{
return (m_firstNum * m_secondNum);
}
private:
int m_firstNum;
int m_secondNum;
};
// 终结符表达式类-除法运算
class DivisionExpression : public AbstarctExpression
{
public:
DivisionExpression(int firstNum, int secondNum)
{
m_firstNum = firstNum;
m_secondNum = secondNum;
}
int interpreter()
{
return (m_firstNum / m_secondNum);
}
private:
int m_firstNum;
int m_secondNum;
};
// 环境类
class Context
{
public:
void setSymbolType(int symbolType)
{
m_symbolType = symbolType;
}
void setNum(string firstNumStr, string secondNumStr)
{
m_firstNumStr = firstNumStr;
m_secondNumStr = secondNumStr;
}
int getResult()
{
int result = -999; // 不支持的运算符默认返回-999
SymbolExpression *pFirstSymbolExpression = new SymbolExpression(m_firstNumStr);
int firstNum = pFirstSymbolExpression->interpreter();
SymbolExpression *pSecondSymbolExpression = new SymbolExpression(m_secondNumStr);
int secondNum = pSecondSymbolExpression->interpreter();
AbstarctExpression *pAbstarctExpression = nullptr;
switch (m_symbolType)
{
case 1: // 加法运算
pAbstarctExpression = dynamic_cast<PlusExpression*>(new PlusExpression(firstNum, secondNum));
break;
case 2: // 减法运算
pAbstarctExpression = dynamic_cast<MinusExpression*>(new MinusExpression(firstNum, secondNum));
break;
case 3: // 乘法运算
pAbstarctExpression = dynamic_cast<MultiExpression*>(new MultiExpression(firstNum, secondNum));
break;
case 4: // 除法运算
pAbstarctExpression = dynamic_cast<DivisionExpression*>(new DivisionExpression(firstNum, secondNum));
break;
default:
cout << "无法解释的运算符,只支持加减乘除运算,请找产品经理提需求增加!" << endl;
break;
}
if (pAbstarctExpression != nullptr)
{
result = pAbstarctExpression->interpreter();
}
return result;
}
private:
string m_firstNumStr;
string m_secondNumStr;
int m_symbolType;
AbstarctExpression *m_pAbstarctExpression;
};
int main()
{
cout << "----------------------解释器模式----------------------" << endl;
string firstNumStr = "10";
string secondNumStr = "2";
Context *pContext = new Context();
cout << "----------------------进行加法运算----------------------" << endl;
pContext->setSymbolType(1);
pContext->setNum(firstNumStr, secondNumStr);
cout << "运算结果:" << pContext->getResult() << endl;;
cout << "----------------------进行减法运算----------------------" << endl;
pContext->setSymbolType(2);
pContext->setNum(firstNumStr, secondNumStr);
cout << "运算结果:" << pContext->getResult() << endl;;
cout << "----------------------进行乘法运算----------------------" << endl;
pContext->setSymbolType(3);
pContext->setNum(firstNumStr, secondNumStr);
cout << "运算结果:" << pContext->getResult() << endl;;
cout << "----------------------进行除法运算----------------------" << endl;
pContext->setSymbolType(4);
pContext->setNum(firstNumStr, secondNumStr);
cout << "运算结果:" << pContext->getResult() << endl;;
pContext->setSymbolType(5);
pContext->setNum(firstNumStr, secondNumStr);
cout << "运算结果:" << pContext->getResult() << endl;
DELETE_PTR(pContext);
std::cout << "Hello World!\n";
getchar();
}
运行结果:
五、解释器模式的优缺点
优点:
1、可扩展性比较好,可以通过继承等机制来扩展文法。
2、易于实现简单文法,语法树中的每个表达式节点类都是相似的,实现其文法较为容易。
3、灵活性强,可以方便的增加新的文法规则。
缺点:
1、可利用场景比较少,在软件开发中定义文法的应用实例比较少。
2、对于复杂的文法比较难维护。
3、容易引起类膨胀,每增加一条文法规则都要增加相应的类。
4、执行效率低,解释器模式采用递归调用方法。
能力有限,如有错误,多多指教。。。
本文为博主原创文章,未经博主允许请勿转载!作者:ISmileLi