前提:领域规则模式

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

典型模式

解析器模式: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. linux常用命令(个人总结)

    1.快捷键: ctrl + l           --------------------清屏 ctrl + c          --------------------退出当前命令 ctrl + ...

  2. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  3. Codeforces963C Cutting Rectangle 【数学】

    错了一个小地方调了一晚上.... 题目大意: 给出最多2E+5种不同的矩形,每种有它的长h和宽v还有数量d,现在你要构造大矩形,使得在上面沿着平行于长或宽的边划刀,切出来的矩形正好是给出的所有矩形.问 ...

  4. 「Splay」区间翻转

    传送门:>Here< 解法分析 用splay来维护这个序列. 一直没有搞明白的是,这里的splay的节点究竟维护的是什么?是权值吗?肯定不是,因为区间是会翻转的,如果维护权值的话很快平衡树 ...

  5. 【XSY2733】Disembrangle DP

    题目描述 有一个\(3\times n\)的网格,一些格子里已经有棋子了,一些格子里还没有. 每次你可以选择往一个没有棋子的格子里放一个棋子,但要满足这个格子上下两个格子都有棋子或左右两个格子都有棋子 ...

  6. 【XSY1081】随机存储器 网络流

    题目描述 Bob有\(2^n\)字节的内存,编号为\([0,2^n-1)\).他想对每个字节的内存分别分配一个值.对于编号为\(i\)的内存,如果它被分配了一个值\(j(0\leq j<2^m) ...

  7. BSGS&扩展BSGS

    BSGS 给定\(a,b,p\),求\(x\)使得\(a^x\equiv b \pmod p\),或者说明不存在\(x\) 只能求\(\gcd(a,p)=1\)的情况 有一个结论:如果有解则必然存在\ ...

  8. Leetcode 349. 两个数组的交集 By Python

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2] 示例 2: 输入: nums1 = [4,9,5], ...

  9. 【Luogu2197】NIM游戏(博弈论)

    题面 洛谷 题解 \(Nim\)游戏模板题 #include<iostream> #include<cstdio> #include<cstdlib> using ...

  10. Glad You Came hdu-6356(ST表 || 线段树)

    第一种用线段树,用两颗数维护区间最大值和区间的最小值,然后更新的时候如果我目前区间内的最大值比我得到的v小,那么我就把这个区间修改成v,如果我的最小值比v大,那么v就是没有用的,直接跳过,然后这样每次 ...