示例问题:
编写示例程序,解析json格式数据。
分析:
像我们程序员日常使用的json解析、正则表达式、更甚者编译器编译代码,这些其实都是一种制定了规则,将一些符号进行翻译,解释成特定的功能,其实这些都用了解释器模式的思想。
解决方案:
json数据示例
{
"ID": 1,
"name": "小明",
"age": 13,
"DetailInfo": [{
"math": 91,
"English": 89
},
{
"math": 93,
"English": 91
}
]
}
Interpreter.h
在该文件中,实现了解析基类IInterpreter、及其子类CCurlyBraces(大括号{}内内容解析)、CBrackets(中括号[]内内容解析)、CGetValueByKey(根据key获取value)。对于json格式数据解析,解析这3种情况即可。{}之间的内容可能有{}或者[],[]之间的内容可能有{}或者[],可通过不断的递归解析,知道能够通过CGetValueByKey(根据key获取value)得到最终的值。
#pragma once
#include <string>
#include <iostream>
//取出{}之间的内容
//取出[]之间的内容
//根据key解析出value
//解析基类
class IInterpreter
{
public:
IInterpreter()
{
}
virtual ~IInterpreter()
{
}
virtual void GetValue(std::string strData) = 0;
};
//大括号{}内内容解析
class CCurlyBraces : public IInterpreter
{
public:
CCurlyBraces()
{
}
//取出{}之间的内容
void GetValue(std::string strData)
{
std::cout << "取出{}之间的内容" << std::endl;
}
};
//中括号[]内内容解析
class CBrackets : public IInterpreter
{
public:
CBrackets()
{
}
virtual ~CBrackets()
{
}
//取出[]之间的内容
void GetValue(std::string strData)
{
std::cout << "取出[]之间的内容(可能为数组)" << std::endl;
}
};
//根据key获取value
class CGetValueByKey : public IInterpreter
{
public:
CGetValueByKey()
{
}
virtual ~CGetValueByKey()
{
}
//根据key取出value
void GetValue(std::string strData)
{
std::cout << "根据key取出value" << std::endl;
}
};
解释器模式的使用:
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式需要解决的是,如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式,包括非终结符表达式和终结符表达式。上面示例中的子类CCurlyBraces(大括号{}内内容解析)、CBrackets(中括号[]内内容解析)为非终结符表达式,可通过不断的递归调用,最终使用终结符表达式得到解释的结果。子类CGetValueByKey(根据key获取value)为终结符表达式,可通过该表达式直接解释出最终的结果。
解释器模式,就意味着可以很容易地改变或者扩展文法,因为该模式使用类来表示文法规则,可以使用继承来改变或者扩展该文法。也比较容易实现文法,因为抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
正则表达式就是解释器模式的一种应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。
何时使用解释器模式:
如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式的不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或者编译器生成器来处理。
返回目录:设计模式(C++实现)(总)