设计模式 行为型模式 解释器模式
解释器模式
非常像自己做过的 c++ primer 里 query 作业.
重点是将需要解释的语言,组织成抽象的语法树,用类去构建语法树.
TextQuery
最开始仅是查询某个单词所在的行数。
文本存储到内存,选择 vector<string>
map 数据结构保存查询结果 map<string, set<int>>, string
为查询单词,set 保存行数
QueryResult result 保存查询结果。
query 函数,
QueryResult query(const string & query_word);
依据 word 返回对应的行号 set<int>
,QueryResult
封装该 set;
有 1 个 display 函数,
其他。
OOP 实现
真正的面向对象,类关系:
Query_base
WordQuery NotQuery BinaryQuery
AndQuery OrQuery
WordQuery 解决单个查询
Query
Query 隐藏继承细节,核心成员是一个指向基类的 base 指针.
核心思想就是封装基类指针!,然后灵活的调用下面的函数.
QueryResult eval(TextQuery & t);
问题最后抽象成为一个布尔查询表达式:
Query q = ~(Query("good") | (Query("boy") & Query("girl")));
QueryResult r= q.eval(TextQuery("xxx.file");
这里调用了很多次构造函数:
1 重载~运算符, 构造了1个Query, query_base 指向OrQuery;
2 OrQuery也是构造出来的,它的参数根据表达式推断,是个 x|x 返回的Query;
构造后,OrQuery的pquery指向x|x;
3 x|x又是重载了|,又构造Query, 同时new了1个OrQuery;
4 OrQuery构造时的参数有2个,分别用2个指针指向:
lquery = &Query("good") ;
Qeury("word")是默认的Query构造,接受string, 5;
rquery = &( x&x )
5 构造Query("word),返回Query
6 x&x 重载&, 返回新Query, 同时构造新的AndQuery
7 AndQuery 构造接收2个Qquery,也有2个指针指向他们
lquery指向Query("boy);
rquery指向Query("girl);
8 构造Query("boy"),返回Query
9 构造Query("girl"),返回Query
一共调用了 9 次…
本质上就是虚函数里再调用虚函数,形成层次, 最外层的优先级最低(~),括号扩起来的优先级别最高(&).
q.eval –>NotQuery::eval NotQuery 里的基类指针,指向了一个 OrQuery
OrQuery::eval, 含有两个指针,一个指向 WordQuery,一个指向 AndQuery, 因此分别调用了 WordQuery::eval 和 AndQuery::eval
WordQuery::eval 检查单词“good” AndQuery::eval 又含 2 个指针(Query 对象),指向 2 个 WordQuery
WordQuery::eval 检查单词“boy” WordQuery::eval 检查单词“girl” 继续做 AndQuery::eval 的 And 动作 继续做 OrQuery::eval 的 Or 动作
继续做 NotQuery::eval 未完成的 Not 动作
例如 Query | Query: 操作返回一个 Query, 用派生类的指针构造。 |
friendly Query operator|(const Query a, const Query b)
{
return new OrQuery(a,b);
}
//这里是隐式转换,调用下面的转换构造函数
Query(Query * ptr) : base(ptr) {}
OrQuery 派生自 BinaryQuery,因此派生类的构造又是调用了基类的构造函数
OrQuery(Query a, Query b) : BinaryQuery(a,b,"|") {}
Binary 将 a,b,保存到自己的成员变量 Query left 和 Query right 中。
智能指针的引入
在创建表达式的 query 时,相当于 Query* base = new OrQuery(…);需要手动释放,用智能指针解决手动释放的问题。 另外定义一个类为 share_ptr 和直接定义一个对象 使用上其实并没有区别,
shared_ptr<Class> ptrc;
Class * c;
Class c;
区别在: 1 内存维护上,ptrc 可以自动管理内存释放,指针分配的内存需要 delete,普通对象跟随生命周期自动析构 2 资源上,对象赋值时发生拷贝,shared_ptr 和指针共享; 3 生命周期 share_ptr 取决引用值,指针 delete,而且必须在定义他的类对象结束之前, 普通对象跟随定义他的类的生命周期