1. 解释器模式(Interpreter Pattern)的定义

(1)定义

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

  ①文法:即语法规则。在解释器模式中每一个语法都将对应一个解释器对象,用来处理相应的语法规则。它对于扩展、改变文法以及增加新的文法规则都很方便。

  ②解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子

  ③在解释器模式中可以通过一种称之为抽象语法树(Abstract Syntax Tree, AST)的图形方式来直观地表示语言的构成,每一棵抽象语法树对应一个语言实例

(2)解释器模式的结构和说明

  

  ①AbstractExpression:定义解释器的接口,约定解释器的解释操作。其中的Interpret接口,正如其名字那样,它是专门用来解释该解释器所要实现的功能。(如加法解释器中的Interpret接口就是完成两个操作数的相加功能)。

  ②TerminalExpression:终结符解释器,用来实现语法规则中和终结符相关的操作,不再包含其他的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的叶子对象,可以有多种终结符解释器。

  ③NonterminalExpression:非终结符解释器,用来实现语法规则中非终结符相关的操作,通常一个解释器对应一个语法规则,可以包含其他解释器,如果用组合模式构建抽象语法树的话,就相当于组合模式中的组合对象。可以有多种非终结符解释器。

  ④Context:上下文,通常包含各个解释器需要的数据或是公共的功能。这个Context在解释器模式中起着非常重要的作用。一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

  ⑤Client:客户端,指的是使用解释器的客户端,通常在这里将按照语言的语法做的表达式转换成使用解释器对象描述的抽象语法树,然后调用解释操作。

【编程实验】四则运算(注意终结符解释器与非终结解释器的划分)

//行为型模式:解释器模式
//场景:四则运算

#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <typeinfo>using namespace std;//*******************************************抽象表达式类***********************************
class Expression
{
public://解析公式和数值,其中var中的key是公式中的参数,value值是具体的数字//如a = 100; b = 20; c = 40virtual int interpreter(map<string, int>& var) = 0;virtual ~Expression(){};
};//变量解析器(终结符表达式)
class VarExpression : public Expression
{string key;
public:VarExpression(string key){this->key = key;}//从map中取出变量的值int interpreter(map<string, int>& var){return var[key];}~VarExpression(){cout << "~VarExpression()" << endl;}
};
//**********抽象运算符号解析器***********************
//抽象运算符号解析器
class SymbolExpression : public Expression
{
protected:Expression* left;Expression* right;
public:SymbolExpression(Expression* left, Expression* right){this -> left = left;this -> right = right;}Expression* getLeft(){return left;}Expression* getRight(){return right;}
};//加法解析器
class AddExpression : public SymbolExpression
{
public:AddExpression(Expression* left, Expression* right): SymbolExpression(left,right){}//把左右两个表达式运算的结果加起来int interpreter(map<string, int>& var){return left->interpreter(var) + right ->interpreter(var);}~AddExpression(){cout << "~AddExpression()" << endl;}
};//减法解析器
class SubExpression : public SymbolExpression
{
public:SubExpression(Expression* left, Expression* right): SymbolExpression(left,right){}//把左右两个表达式运算的结果相减int interpreter(map<string, int>& var){return left->interpreter(var) - right ->interpreter(var);}~SubExpression(){cout << "~SubExpression()" << endl;}
};//*********************************解析器封装类***************************************
//解析器封装类,这个类是根据迪米特法则进行封装,目的是让Client只与直接朋友打交道,相当于Facade
class Calculator
{
private:Expression* expression;
public://构造函数传参,并解析表达式,构建语法树Calculator(string expStr){expression = NULL;//栈,用来暂存中间结果stack<Expression*> stkExp;Expression* left  = NULL;Expression* right = NULL;/*从左到向分析表达式(如:a+b-c),最终的语法树如下:*           -*         /   \*       +     c*     /   \*    a     b*/for(unsigned int i = 0; i< expStr.length(); i++){switch(expStr[i]){case '+':  //加法//1.先从栈中取出左操作数left = stkExp.top();stkExp.pop();//2.从表达式中取出+号后面的右操作数,并生成终结符解析对象right = new VarExpression(expStr.substr(++i,1));//3.将左右操作数相加,并把结果放入栈中stkExp.push(new AddExpression(left, right));break;case '-'://1.先从栈中取出左操作数left = stkExp.top();stkExp.pop();//2.从表达式中取出+号后面的右操作数,并生成终结符解析对象right = new VarExpression(expStr.substr(++i,1));//3.将左右操作数相减,并把结果放入栈中stkExp.push(new SubExpression(left, right));break;default://如果是变量(终结符):如a+b+c中的a\b\c,//则直接生成对应的变量解析器对象stkExp.push(new VarExpression(expStr.substr(i,1)));}}//栈中保存的就是最终语法树的根结点(本例为SuuExpression对象)if(!stkExp.empty()){expression = stkExp.top();stkExp.pop();}}void deltree(Expression* expression){SymbolExpression* branch = dynamic_cast<SymbolExpression*>(expression);//叶子结点if (branch == NULL){delete expression;}else  //分支结点
        {//左子树deltree(branch->getLeft());//右子树deltree(branch->getRight());//结点delete expression;}}~Calculator(){deltree(expression);expression = NULL;}//开始运算int run(map<string, int>& var){return (expression == NULL) ? 0 : expression->interpreter(var);}
};
int main()
{string expStr = "a+b-c"; //为简化处理,这里必须是合法的表达式
map<string, int> var;   //相当于Interpreter模式中的Contextvar["a"] = 100;var["b"] = 20;var["c"] = 40;Calculator cal(expStr);cout <<"运算结果为:" << expStr << " = " << cal.run(var) << endl;return 0;
}
/*
运算结果为:a+b-c = 80
~VarExpression()
~VarExpression()
~AddExpression()
~VarExpression()
~SubExpression()
*/

2. 思考解释器模式

(1)解释器模式的本质分离实现,解释执行。通过一个解释器对象处理一个语法规则的方式,把复杂的功能分离开,然后选择需要被执行的功能,并把这些功能组合成需要解释执行的抽象语法树,再按照抽象语法树来解释执行,实现相应的功能。从本质上看,解释器模式的思路仍然是分离、封装和简化,这与很多其他模式是一样的。

(2)谁来构建抽象语法树——解析器

  解析器的工作主要就是用来构建抽象语法树的,这个角色会客户端转来的语言,负责按语法规则,生成一个个解释器,并将这些解释器组合成一颗抽象语法树。注意,解析器的工作主要是构造语法树,而解释器的工作是解释这颗语法树

(3)谁来负责解释操作  ——解释器(Interpreter)

  只要定义好了抽象语法树,肯定是解释器来负责解释执行,而选择解释器的工作,在构建抽象语法树的时候就完成了,一般由根结点的解释器开始解释,然后递归地调用其他解释器。

【编程实验】中文数字转阿拉伯数字(注意Context的应用)

//行为型模式:解释器模式
//场景:中文数字转阿拉伯数字
/*
1、使用Interpreter模式来将中文数字转换为数学数字的好处是可以应对中文数字的变化,
虽然可以用一很好的算法将中文转化为数字,解释器的扩展性能比较好,如果出现亿、兆的情况,
可以写出两个类(YiExpression、ZhaoExpression)来继承Expression类,而其他地方的代码都不变化。
2、思路:用单位用分解出不同的解释器.其中个位、十位、百位和千位是终结符解释器,万位是非结终符解释器,因为万以上的单位可以形成如果九百零一万之类的数字,需要进一进拆分成由结终符构成的解释器来完成任务。
3、转化:将中文数字串由低位向高位方向不断转化*/
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <list>using namespace std;//字符串上下文信息:保存没有处理的字符串信息
class Context
{
private:string statement;int data;
public:Context(string statement){this ->statement = statement;data = 0;}string& getStatement(){return  statement;}void setStatement(string statement){this -> statement = statement;}int getData(){return data;}void setData(int data){this -> data = data;}
};//抽象类:解释器
class Expression
{
protected://数据字典:保存中文数字一到九static map<string, int> table;//辅助函数,用来判判断src字符串是否以tail串结尾bool stringEndsWith(const string& src, const string& tail){if(src.size() < tail.size())return false;string tmp = src.substr(src.size() - tail.size(), tail.size());return (0==tmp.compare(0,tail.size(),tail));}
public://虚方法:中文数字到数字的转换virtual void interpret(Context& context){if(context.getStatement().length() == 0)return;map<string, int>::iterator iter = table.begin();while (iter != table.end()){string& statement = context.getStatement();string tail = iter->first + getPostfix();//从低位往高位分析(如九千三百零五,从右向左分析)if(stringEndsWith(statement,tail)){context.setData(context.getData() + iter->second * multiplier());//注意,string是ASCII编码,每个中文字符的长度为2context.setStatement(statement.substr(0, statement.length()-2 - getPostfix().length()));}if(stringEndsWith(statement,"零")){//”零“则直接跳过context.setStatement(statement.substr(0, statement.length()-2));}++iter;}}//表达式的后缀是以什么表示的(十、百...)virtual string getPostfix() = 0;//表达式的数量级virtual int multiplier() = 0;virtual ~Expression(){};
};//映射表,保存中文数字与罗马数字的映射
static map<string, int>::value_type init_table[] =
{map<string, int>::value_type("一",1),map<string, int>::value_type("二",2),map<string, int>::value_type("三",3),map<string, int>::value_type("四",4),map<string, int>::value_type("五",5),map<string, int>::value_type("六",6),map<string, int>::value_type("七",7),map<string, int>::value_type("八",8),map<string, int>::value_type("九",9)
};map<string,int> Expression::table(init_table,init_table + 9);//个位数解释器(终结符表达式)
class GeExpression : public Expression
{
public:string getPostfix(){return "";}int multiplier(){return 1;}
};//十位数解释器(终结符表达式)
class ShiExpression  : public Expression
{
public:string getPostfix(){return "十";}int multiplier(){return 10;}
};//百位数解释器(终结符表达式)
class BaiExpression  : public Expression
{
public:string getPostfix(){return "百";}int multiplier(){return 100;}
};//千位数解释器(终结符表达式)
class QianExpression : public Expression
{
public:string getPostfix(){return "千";}int multiplier(){return 1000;}
};//万位数解释器(非终结符表达式)
class WanExpression : public Expression
{
public:string getPostfix(){return "万";}int multiplier(){return 10000;}void interpret(Context& context){if(context.getStatement().length() == 0)return ;if (stringEndsWith(context.getStatement(),getPostfix())){list<Expression*> exps;exps.clear();exps.push_back(new GeExpression());exps.push_back(new ShiExpression());exps.push_back(new BaiExpression());exps.push_back(new QianExpression());int temp = context.getData();string& sm = context.getStatement();context.setData(0);//string类中每个中文长度为2.context.setStatement(sm.substr(0, sm.length()-2));list<Expression*>::iterator iter = exps.begin();while (iter != exps.end()){(*iter)->interpret(context);++iter;}context.setData(temp + multiplier()* context.getData());iter = exps.begin();while (iter != exps.end()){delete (*iter);++iter;}exps.clear();}}
};//转换器
class Convertor
{
private:Context context;string chineseNum;int result;list<Expression*> exps;void reset(){context.setStatement(chineseNum);context.setData(0);list<Expression*>::iterator iter = exps.begin();while (iter != exps.end()){delete (*iter);++iter;}exps.clear();}public:Convertor(const string chineseNum):context(chineseNum){this ->chineseNum = chineseNum;result = 0;}void convert(){reset();exps.push_back(new GeExpression());exps.push_back(new ShiExpression());exps.push_back(new BaiExpression());exps.push_back(new QianExpression());exps.push_back(new WanExpression());list<Expression*>::iterator iter = exps.begin();while (iter != exps.end()){(*iter)->interpret(context);++iter;}result = context.getData();}int getRoman(){return result;}void setChineseNum(const string& chineseNum){this ->chineseNum = chineseNum;}~Convertor(){reset();}
};int main()
{string chineseNum = "四百九十六万二千三百一十五";Convertor conv(chineseNum);conv.convert();cout << chineseNum << " -> " << conv.getRoman() << endl;chineseNum = "九千零五万六千零七十二";conv.setChineseNum(chineseNum);conv.convert();cout << chineseNum << " -> " << conv.getRoman() << endl;return 0;
}
/*输出结果:
四百九十六万二千三百一十五 -> 4962315
九千零五万六千零七十二 -> 90056072
*/

3. 解释器模式的优缺点

(1)优点

  ①易于实现文法:在解释器模式中,一条语法规则用一个解释器对象来解释执行。对于解释器的实现来讲,功能就变得比较简单,只需要考虑这一条语法规则的实现就可以了,其他的都不用管。

  ②易于扩展新的语法。由于解释器采用类来描述语法规则,因此可以通过继承等机制创建相应的解释器对象,在创建抽象语法树的时候使用这个新的解释器对象就可以了。

(2)缺点

  ①执行效率较低。由于在解释器模式中使用了大量的循环和递归调用,因此在解释较为复杂的句子时其速度很慢,而且代码的调试过程也比较麻烦。

  ②对于复杂文法难以维护。在解释器模式中,每一条规则至少需要定义一个类,因此如果一个语言包含太多文法规则,类的个数将会急剧增加,导致系统难以管理和维护,此时可以考虑使用语法分析程序等方式来取代解释器模式。

4. 解释器模式的应用场景

(1)当一个语言需要解释执行,并可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式(如XML文档解释、正则表达式等领域)

(2)一些重复出现的问题可以用一种简单的语言来进行表达。

(3)一个语言的文法较为简单.

(4)当执行效率不是关键和主要关心的问题时可考虑解释器模式(注:高效的解释器通常不是通过直接解释抽象语法树来实现的,而是需要将它们转换成其他形式,使用解释器模式的执行效率并不高。)

【编程实验】机器人控制程序

//行为型模式:解释器模式
//场景:开发一套机器人控制程序
/*说明:机器人控制程序中包含一些简单的英文控制指令,每一个指令对应一个表达式(expression),该表达式可以是简单表达式也可以是复合表达式,每一个简单表达式由移动方向(direction),移动方式(action)和移动距离(distance)三部分组成,其中移动方向包括上(up)、下(down)、左(left)、右(right);移动方式包括移动(move)和快速移动(run);移动距离为一个正整数。两个表达式之间可以通过与(and)连接,形成复合(composite)表达式。用户通过对图形化的设置界面进行操作可以创建一个机器人控制指令,机器人在收到指令
后将按照指令的设置进行移动,例如输入控制指令:up move 5,则“向上移动5个单位”;输入控
制指令:down  run 10 and left move 20,则“向下快速移动10个单位再向左移动20个单位”。
*//*文法规则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,它们都是一个完整的句子,包含一系列终结符或非终结符。
*///本实例对机器人控制指令的输出结果进行模拟,将英文指令翻译为中文指令,实际情况是调用不同的控制程序进行机器人的控制,
//包括对移动方向、方式和距离的控制等
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <typeinfo>using namespace std;//
// 字符串分割
//
// -------------------------------------------------------------------------
// 函数     : Split
// 功能     : 分割STL标准字符串
// 返回值   : void
// 参数     : Container<std::basic_string<CharT> >& v 存放分割结果
// 参数     : const std::basic_string<CharT>& s 待分割字符串
// 参数     : const std::basic_string<CharT>& c 分割字符串
// -------------------------------------------------------------------------
template<typename CharT, template<typename S, typename Q = std::allocator<S> > class Container>
void Split(Container<std::basic_string<CharT> >& v, const std::basic_string<CharT>& s, const std::basic_string<CharT>& c);template<template<typename S, typename Q = std::allocator<S> > class Container>
void Split(Container<std::basic_string<char> >& v, const std::basic_string<char>& s, const std::basic_string<char>& c)
{if (0 == c.length())return;std::basic_string<char>::size_type pos1 = 0;std::basic_string<char>::size_type pos2 = 0;pos1 = 0;pos2 = s.find(c);while (std::basic_string<char>::npos != pos2){v.push_back(s.substr(pos1, pos2 - pos1));pos1 = pos2 + c.size();pos2 = s.find(c, pos1);}if (pos1 != s.length()){v.push_back(s.substr(pos1));}
}//抽象类:解释器
class AbstractExpression
{
public:virtual string interpret() = 0;virtual ~AbstractExpression(){}
};
//And解释器:非终结符表达式
class AndExpression : public AbstractExpression
{
private:AbstractExpression* left ; //And的左表达式AbstractExpression* right; //And的右表达式
public:AndExpression(AbstractExpression* left,AbstractExpression* right){this->left  = left;this->right = right;}//And表达式解释操作string interpret(){return left->interpret() + "再" + right->interpret();}AbstractExpression* getLeft(){return left;}AbstractExpression* getRight(){return right;}
};//简单句子解释器:非终结符表达式
//如:up move 5,表示“向上移动5个单位
class SentenceExpression : public AbstractExpression
{
private:AbstractExpression* direction;AbstractExpression* action;AbstractExpression* distance;
public:SentenceExpression(AbstractExpression* direction,AbstractExpression* action,AbstractExpression* distance){this->direction = direction;this->action = action;this->distance = distance;}//解释操作string interpret(){return direction->interpret() + action->interpret() + distance->interpret();}AbstractExpression* getDirection(){return direction;}AbstractExpression* getAction(){return action;}AbstractExpression* getDistance(){return distance;}
};//方向解释器:终结符表达式
class DirectionExpression : public AbstractExpression
{
private:string direction;
public:DirectionExpression(string direction){this->direction = direction;}//方向表达式的解释操作string interpret(){if(direction =="up"){return "向上";}else if(direction == "down"){return "向下";}else if(direction == "left"){return "向左";}else if(direction == "right"){return "向右";}else{return "无效指令";}}
};//动作解释器:(终结符表达式)
class ActionExpression : public AbstractExpression
{
private:string action;
public:ActionExpression(string action){this->action = action;}//动作移动表达式的解释操作string interpret(){if(action == "move"){return "移动";}else if(action == "run"){return "快速移动";}else{return "无效指令";}}
};//距离解释器:(终结符表达式)
class DistanceExpression : public AbstractExpression
{
private:string distance;
public:DistanceExpression(string distance){this->distance = distance;}string interpret(){return distance;}
};//指令处理类:工具类
class InstructionHandler
{
private:AbstractExpression* mExp;void delTree(AbstractExpression* exp)  //删除最终的生成的抽象树
    {//叶子结果bool bLeaf = typeid(*exp) ==typeid(DirectionExpression) ||typeid(*exp) ==typeid(ActionExpression) ||typeid(*exp) ==typeid(DistanceExpression);AndExpression* andExp = dynamic_cast<AndExpression*>(exp);SentenceExpression* sentenceExp = dynamic_cast<SentenceExpression*>(exp);if(bLeaf){delete exp;}else if (andExp != NULL)  //And表达式
        {AbstractExpression* left = andExp->getLeft();AbstractExpression* right = andExp->getRight();delTree(left);delTree(right);delete andExp;}else if(sentenceExp != NULL) //简单句子表达式
        {AbstractExpression* dir = sentenceExp->getDirection();AbstractExpression* act = sentenceExp->getAction();AbstractExpression* dis = sentenceExp->getDistance();delTree(dir);delTree(act);delTree(dis);delete sentenceExp;}else{}}
public:InstructionHandler():mExp(NULL){}void handle(string instruction){AbstractExpression* left = NULL;AbstractExpression* right = NULL;AbstractExpression* direction = NULL;AbstractExpression* action = NULL;AbstractExpression* distance = NULL;if (mExp!=NULL){delTree(mExp);mExp = NULL;}//声明一个栈对象用于存储抽象语法树stack<AbstractExpression*> stkExp;vector<string> words;Split(words, instruction, " "); //以空格分隔指令字符串for(unsigned int i=0; i<words.size(); i++){//本实例采用栈的方式来处理指令,如果遇到and则将其后的三个单词连成一个简单句子(Sentence)//作为"and"的右表达式,而将栈顶弹出的表达式作为"and"的左表达式,最后将新的And表达式压入栈中string dir("");string act("");string dis("");if(words[i] =="and"){//从弹出栈顶作为and的左表达式left = stkExp.top();stkExp.pop();dir = words[++i];direction = new DirectionExpression(dir);act = words[++i];action = new ActionExpression(act);dis = words[++i];distance = new DistanceExpression(dis);//组成一个简单表达式作为And的右表达式right = new SentenceExpression(direction, action, distance);//生成And表达式,并压入栈中stkExp.push(new AndExpression(left, right));}//如果不是and表达式,就从头开始进行解释,将前3个单词作为Sentence//的三个操作数,生成简单表达式解析器后压入栈中else{dir = words[i];direction = new DirectionExpression(dir);act = words[++i];action = new ActionExpression(act);dis = words[++i];distance = new DistanceExpression(dis);//组成一个简单表达式作为And的右表达式stkExp.push(new SentenceExpression(direction, action, distance));}}if(!stkExp.empty()){mExp = stkExp.top();stkExp.pop();}elsemExp = NULL;}string output(){return mExp==NULL ? "": mExp->interpret();}
};int main()
{string instruction = "up move 5 and down run 10 and left move 5";InstructionHandler handler;handler.handle(instruction);cout <<"输入指令: " <<instruction <<endl;cout <<"移动结果:" << handler.output() << endl;instruction = "right run 20 and down move 10 and left run 40 and up run 10";handler.handle(instruction);cout <<"输入指令: " <<instruction <<endl;cout <<"移动结果:" << handler.output() << endl;return 0;
}
/*输出结果:
输入指令: up move 5 and down run 10 and left move 5
移动结果:向上移动5再向下快速移动10再向左移动5
输入指令: right run 20 and down move 10 and left run 40 and up run 10
移动结果:向右快速移动20再向下移动10再向左快速移动40再向上快速移动10
*/

5. 相关模式

(1)解释器和组合模式

这两种可以组合使用,一般非终结符解释器相当于组合模式中的组合对象,终结符解释器相当于叶子对象。

(2)解释器模式和迭代器模式

由于解释器模式通常使用组合模式来实现,因此在遍历整个对象结构时,可以使用迭代器模式。

(3)解释器模式和享元模式

在使用解释器模式的时候,可能会造成多个细粒度对象,如各式各样的终结符解释器,而这些终结符解释器对不同的表达式来说是一样的,是可以共用的,因此可以引入享元模式来共享这些对象。

(4)解释器模式和访问者模式

在解释器模式中,语法规则和解释器对象是有对应关系的。语法规则的变动意味着功能的变化。自然会导致使用不同的解释器对象;而且一个语法规由可以被不同的解释器解释执行。因此在构建抽象语法树的时候,如果每个节点所对应的解释器对象固定的,这意味着该节点对应的功能是固定的,那么就不得不根据需要来构建不同的抽象语法树。

为了让构建的抽象语法树较为通用,那就要求解释器的功能不要那么固定,要能很方便地改变解释器的功能,这个时候就变成了如何能够很方便地更改树形结构中节点对象的功能了,访问者模式可以很好的实现这个功能。

设计模式C++实现(20)——解释器模式相关推荐

  1. java蝇量模式_Head First设计模式——蝇量和解释器模式

    蝇量 蝇量模式:如果让某个类的一个实例能用来提供许多"虚拟实例",就使用蝇量模式. 在一个设计房子的平台中,周围要加上一些树,树有一个坐标XY坐标位置,而且可以根据树的年龄动态将自 ...

  2. 「补课」进行时:设计模式(20)——解释器模式

    1. 前文汇总 「补课」进行时:设计模式系列 2. 解释器模式 解释器模式这个模式和前面的访问者模式比较像,当然,我说的比较像是难的比较像,以及使用率是真的比较低,基本上没有使用的场景,访问者模式还有 ...

  3. 设计模式(20)解释器模式

    **定义:**给定一种语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子. **类型:**行为类模式 类图: ​ 解释器模式是一个比较少用的模式,本人之前也没有用过这个 ...

  4. 设计模式的理解:解释器模式 Interpreter

    解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式.这种模式实现了一个表达式接口,该接口解释一个特定的上下文.这种模式被用在 SQL 解析.符号处 ...

  5. 设计模式之禅【解释器模式】

    真刀实枪之解释器模式 从模型公式说起 需求,输入一个模型公式,然后输入模型中的参数,运算出结果 设计要求 公式可以运行时编辑 高扩展性 效率可以暂不考虑 分析下这个需求,还是比较简单的,就是有一套模板 ...

  6. 【Java设计模式】简单学解释器模式——加减乘除

    目录 说明 实现方式 应用场景 其他链接 说明 行为型模式之一,其他还有命令模式.模板方法模式.访问者模式.观察者模式.中介者模式.备忘录模式.迭代器模式.状态模式.策略模式.职责链模式(责任链模式) ...

  7. Android设计模式详解之解释器模式

    前言 解释器模式是一种使用较少的行为型模式: 提供了一种解释语言的语法或表达式的方式,通过该接口解释一个特定的上下文. 定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示 ...

  8. 《设计模式之禅》-解释器模式

    解释器模式是一种按照规定语法进行解析的方案,在现在的项目中使用比较少 定义 给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子 AbstractExpress ...

  9. 设计模式のInterpreter Patern(解释器模式)----行为模式

    一.问题产生背景 有一句话"小明和小龙是好朋友",我想分析其中谁是人,我想分析他们的关系等多种需求,那么我们应该如何处理,如果为每一个关系都进行判断?显然不合适,我们可以将二者的关 ...

  10. C++23种设计模式(23)-解释器模式

    解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.解释器模式解决的问题是,如果一种特定类型的问题发生的频率足够高,那么可能就只得将该问题的各个 ...

最新文章

  1. java冒泡排序函数验证_java冒泡排序-选择排序-插入排序-使用API中文文档直接调用函数...
  2. 苹果的新Siri:不男,也不女
  3. mysql 同步备份数据库
  4. 全景视频的跟踪与合成方法
  5. 信号与系统第四章-第六章习题易错点整理
  6. adapt和adopt的区别_脸盲了,adopt和adapt要如何区分?
  7. 虚函数和纯虚函数的区别?
  8. php查询MySQL结果转化为数组_PHP如何将SQL查询结果转为多维数组,并按查询行输出...
  9. HTTP的长连接和短连接
  10. Linux开发商计划停止开发32位版本
  11. “洗净净”、“洗香香”、“洗爽爽” 京东又申请了这些商标
  12. 《Entity Framework 6 Recipes》中文翻译系列 (42) ------ 第八章 POCO之使用POCO
  13. jsp购物车简单实现思想(一)
  14. 二叉树期CRR权定价模型-python
  15. 【记Unexpected token】
  16. 北京驾照到期后如何在郑州换证
  17. 宝塔搭建腾讯云轻量级云服务器基本步骤
  18. 如何顺利获得美国工作签证
  19. onkeypress,onkeydown,onkeyup区别
  20. 城市槽音乐在津巴布韦的美国音乐如何影响其他文化和身份的个案研究

热门文章

  1. python解析xml数据_用Python解析XML数据
  2. 单一世界架构初探之边界冲突
  3. beeline:No current connection
  4. 2020年了,ERP真的快要消失了吗?
  5. 【预测模型】基于 bp神经网络风电功率预测matlab源码
  6. Gotomeeting在视频会议行业的应用趋势分析
  7. 电子挂历(万年历)样式
  8. AutoCAD 2020 简体中文版 珊瑚版
  9. 王帅:深入PHP内核(二)——SAPI探究
  10. Android点亮屏幕或屏幕解锁和锁定