前提:领域规则模式

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

典型模式

解析器模式: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. puppet的常用语法

    检查语法错误 puppet parser validate xx.pp 在客户端测试但是不应用 puppet agent --test --noop 基于安全的考虑,使用预签名证书 puppet ce ...

  2. 网页调起QQ聊天

    将QQ账号换成正常的QQ号即可,要确保这个QQ支持临时会话 <a href="http://wpa.qq.com/msgrd?v=3&uin=QQ账号&site=qq& ...

  3. Navicat MySQL 自动备份

    1 新建批处理作业 2 设定(多个库,就轮流选择不同库,然后步骤2) 最后记得保存 3 计划 4 设计批处理作业->设置计划任务 5 输入账号和密码 服务器登录名 服务器密码 6 你可以修改备份 ...

  4. 洛谷p1586四方定理题解

    题目 这个题的本质是动态规划中的背包问题. 为什么会想到背包呢. 因为往往方案数不是排列组合就是递推或者是dp,当然还有其他的可能.我们可以把一个数的代价当成这个数的平方,价值就是一个方案数.由于这个 ...

  5. 洛谷p1091合唱队形题解

    题目 合唱队形首先要满足的是从1这个位置到中间任意的位置为单增的,从中间任意的位置到最后是单减的,且长度最长.这样才能满足出列的同学最少. 如果要满足这个条件那么我们可以先预处理出每个点的从前找的最长 ...

  6. FFT算法小结

    都应该知道多项式是什么对吧(否则学什么多项式乘法) 我们用\(A(x)\)表示一个\(n-1\)次多项式,即\(A(x)=\sum_{i=0}^{n-1} {a_i}*x^i\) 例如\(A(x)=x ...

  7. java session创建与获取

    一.流程 登录接口-->验证用户名密码-->获取用户实体对象-->创建session (key,value) 其他接口调用-->获取session(key) 二.代码 //登录 ...

  8. 【NOI2003——搜索+二分图匹配优化】

    A 文本编辑器 无旋treap真好看 B 木棒游戏 暴力神仙题 C 数据生成器 树的直径两端点为Y, Z D 智破连环阵 搜索+二分图匹配优化 第一次写欸 列一下 void dfs (int y,in ...

  9. 本文之后都以Vol1来指代

    本文参考文档是<64-ia-32-architectures-software-developer-vol-1-manual>(本文之后都以Vol1来指代),介绍了x86架构的基础.这些基 ...

  10. HR_Hash Tables: Ransom Note

    1 题目重点:whole words | case-sensitive #!/bin/python3 import math import os import random import re imp ...