前提:领域规则模式

在特定领域内,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出该领域下的一般性解决方案。

典型模式

解析器模式:Interpreter

一:解释器模式Interpreter

(一)概念

一些应用提供了内建(Build-In)的脚本或者宏语言来让用户定义他们能够在系统中进行的操作。
Interpreter模式的目的就是使用一个解释器为用户提供一个一门定义语言的语法表示的解释器,然后通过解释器来解释语言中的句子。
Interpreter模式提供了一个实现语法解释器的框架。

(二)动机

在软件构建过程中,如果某一特定领域的问题比较复杂,类似的结构不断的重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解析器来解释这样的句子,从而达到解决问题的目的。

(三)代码分析(加减运算)

利用操作树来实现语法规则提取
string expStr = "a+b-c+d";  //使用表达式树来表示规则

0.表达式基类

class Expression {
public:
virtual int interpreter(map<char, int> var)=0;  //解析结果
virtual ~Expression(){}
};

1.构建变量表达式(叶子结点)

//变量表达式
class VarExpression: public Expression { char key; public:
VarExpression(const char& key)
{
this->key = key;
} int interpreter(map<char, int> var) override {
return var[key];
}
};

2.符号表达式(树结点基类)

//符号表达式
class SymbolExpression : public Expression { // 运算符左右两个参数
protected:
Expression* left;
Expression* right; public:
SymbolExpression( Expression* left, Expression* right):
left(left),right(right){
} };

3.符号表达式子类实现(树结点),进行执行

//加法运算
class AddExpression : public SymbolExpression { public:
AddExpression(Expression* left, Expression* right):
SymbolExpression(left,right){ }
int interpreter(map<char, int> var) override {
return left->interpreter(var) + right->interpreter(var);  //执行操作
} }; //减法运算
class SubExpression : public SymbolExpression { public:
SubExpression(Expression* left, Expression* right):
SymbolExpression(left,right){ }
int interpreter(map<char, int> var) override {
return left->interpreter(var) - right->interpreter(var);
} };

4.解析表达式(获取的是解析的表达式,不是结果)

Expression*  analyse(string expStr) {

    stack<Expression*> expStack;  //使用栈来存储表达式
Expression* left = nullptr;
Expression* right = nullptr;
for(int i=; i<expStr.size(); i++)
{
switch(expStr[i])
{
case '+':
// 加法运算
left = expStack.top();  //获取栈顶数据做左运算数
right = new VarExpression(expStr[++
i]);  //获取表达式下一个数做有运算数
expStack.push(new AddExpression(left, right));  //将运算结果入栈
break;
case '-':
// 减法运算
left = expStack.top();
right = new VarExpression(expStr[++i]);
expStack.push(new SubExpression(left, right));
break;
default:
// 变量表达式
expStack.push(new VarExpression(expStr[i]));  //不是符号,我们就进行入栈操作
}
} Expression* expression = expStack.top();  //获取最后栈顶表达式返回出去就是结果 return expression;
}

5.表达式树构建

int main(int argc, const char * argv[]) {

    string expStr = "a+b-c+d-e";  //结构类似,容易抽象为语法规则,业务频繁变化
map<char, int> var;
var.insert(make_pair('a',));
var.insert(make_pair('b',));
var.insert(make_pair('c',));
var.insert(make_pair('d',));
var.insert(make_pair('e',)); Expression* expression= analyse(expStr); int result=expression->interpreter(var);  //使用解析得到的表达式,可以获取结果返回 cout<<result<<endl; release(expression); return ;
}

6.释放空间,释放顺序下至上

void release(Expression* expression){

    //释放表达式树的节点内存...
}

(四)模式定义

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

                                                                     ——《设计模式》GoF

(五)类图(结构)

(六)要点总结

(一)Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。

(二)使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。

(三)Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。

(七)案例实现(没有上面讲解使用的案例好)

#include <iostream>
using namespace std;
#include "string" class Context
{
public:
Context(int num)
{
m_num = num;
}
public:
void setNum(int num)
{
m_num = num;
}
int getNum()
{
return m_num;
}
void setRes(int res)
{
m_res = res;
}
int getRes()
{
return m_res;
} private:
int m_num;
int m_res;
}; class Expression
{
public:
virtual void interpreter(Context *context) = ;
}; class PlusExpression:public Expression
{
public:
virtual void interpreter(Context *context)
{
int num = context->getNum();
num++;
context->setNum(num);
context->setRes(num);
}
}; class MinusExpression:public Expression
{
public:
virtual void interpreter(Context *context)
{
int num = context->getNum();
num--;
context->setNum(num);
context->setRes(num);
}
}; int main(void)
{
Context *pcxt = new Context(); Expression *e1 = new PlusExpression();
e1->interpreter(pcxt);
cout << "PlusExpression:" << pcxt->getRes() << endl; Expression *e2 = new MinusExpression();
e2->interpreter(pcxt);
cout << "MinusExpression:" << pcxt->getRes() << endl; delete e1;
delete e2; system("pause");
return ;
}

设计模式---领域规则模式之解析器模式(Interpreter)的更多相关文章

  1. Java进阶篇设计模式之五-----外观模式和装饰器模式

    前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...

  2. Java设计模式之五 ----- 外观模式和装饰器模式

    前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...

  3. 深入探索Java设计模式(三)之装饰器模式

    装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类.这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用.本文是在学习完优锐课JAVA架构VIP课程—[框架源码专题 ...

  4. dom4j解析器 基于dom4j的xpath技术 简单工厂设计模式 分层结构设计思想 SAX解析器 DOM编程

    *1 dom4j解析器   1)CRUD的含义:CreateReadUpdateDelete增删查改   2)XML解析器有二类,分别是DOM和SAX(simple Api for xml).     ...

  5. 设计模式---对象创建模式之构建器模式(Builder)

    一:概念 Builder模式也叫建造者模式或者生成器模式,是由GoF提出的23种设计模式中的一种.Builder模式是一种对象创建型模式之一,用来隐藏复合对象的创建过程,它把复合对象的创建过程加以抽象 ...

  6. IOS设计模式之二(门面模式,装饰器模式)

    本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq) ...

  7. 设计模式---行为变化模式之访问器模式(Visitor)

    一:概念 访问者模式,是行为模式之一,它分离对象的数据和行为,使用Visitor模式,可以不修改已有类的情况下,增加新的操作角色和职责. 二:动机 在软件构建的过程中,由于需求的改变,某些类层次结构中 ...

  8. 面向对象程序设计(OOP设计模式)-结构型模式之装饰器模式的应用与实现

    课程名称:程序设计方法学 实验4:OOP设计模式-结构型模式的应用与实现 时间:2015年11月18日星期三,第3.4节 地点:理1#208 一.实验目的 加深对结构型设计模式的理解以及在开发中的实际 ...

  9. Java设计模式(七)Decorate装饰器模式

    一.场景描述 (一)问题 系统中最初使用Crystal Report(水晶报表)工具生成报表,并将报表发送给客户端查看,此时定义一CrystalReport工具类即可完成水晶报表的生成工作. 后续报表 ...

随机推荐

  1. kubernetes Helm基本操作

    创建: helm install --name demo --set Persistence.Enabled=false stable/jenkins 查看: kubectl get po,svc - ...

  2. POJ 2299 -Ultra-QuickSort-树状数组求逆序数

    POJ 2299Ultra-QuickSort 使用树状数组记录逆序对数. 把数组按照大小顺序插入,getsum(i)就是i前面的比他大的数. #include <cstdio> #inc ...

  3. Mysql 数据备份导出

    mysqldump导出整个数据库mysqldump --single-transaction --skip-lock-tables -uDBUSER -pDBPASSWD -hDBIP \--defa ...

  4. __init__、__new__、__call__ 方法

    __init__方法 __init__方法负责对象的初始化,系统执行该方法前,其实该对象已经存在了,要不然初始化什么东西呢?先看例子: # class A(object): python2 必须显示地 ...

  5. AXURE 8弄一个轮播图的步骤

    这个图是网上找到,7.0可以使用. 如果是8.0.没有找到"动态面板"这个地方,如下图所示

  6. CANOE入门(二)

    CAPL就是Communication Application Programming Laguage的缩写,CAPL类似于C语言的语法,因此所有的语法请参考C语言教程,这里不在这里进行详述,关于C语 ...

  7. centos7/RHEL7最小化系统安装gnome图形界面

    应用场景:对于比较熟悉linux系统的用户来说,全命令行系统可能来的比较简单明了高效,也存在某些情况下需要有像winodws下弹出对话框的情形需求,或者对于初识linux习惯windows界面的用户来 ...

  8. bzoj2553 禁忌

    题目链接 题意 给出一个\(n\)个字符串的字典.对于一个字符串,他的贡献是这个字符串中最多的在字典中出现的不重叠子串的数量. 然后问一个长度为\(len\)的,字符集为前\(alphabet\)个字 ...

  9. 第二十三篇-ubuntu18.04怎么下载播放器以及如何设置默认播放器

    下载播放器 安装命令:sudo apt-get install smplayer再安装解码器: 安装win32codecs包 如果是intel的CPU 代码: sudo apt-get install ...

  10. qrcode.js 动态生成二维码

    用qrcode.js动态生成二维码图片非常简单,只需要引入qrcode.js即可使用,而且可以自定义图片大小.背景色等信息. 1.jsp代码---页面头部引入qrcode.js,jquery文件可选 ...