当有一个语言需要解释执行,并且你可以将语言中的句子表示为一个抽象语法树时,可使用解释器模式。
INTERPRETER(解释器)
适用性:
当有一个语言需要解释执行,并且你可以将语言中的句子表示为一个抽象语法树时,可使用解释器模式。
思考:
一个常见使用情况当然是操纵一种程序语言,例如JavaScript,Python。这个时候,我们通常使用一个脚本引擎库来实现解释器。然而,并不是所有语言都是程序语言,解释器模式更多的时候可以用来处理非程序语言,例如正则表达式。语言的规则也可以简单,也可以复杂,通常,解释器是一个引擎。XML的解析引擎,也可以看做解释器模式。因此,可以认为:针对程序语言的实现,是一种强化的实现;针对简单到极点的语言(表格),可以看作是退化的实现。解释器的目的是希望通过数据(语言)来推动逻辑。一般意义上的数据缺乏足够的表现力,因此不具备显著地改变程序行为的能力。
INTERPRETER并非高不可及,完全可以在一些平凡的地方发挥作用。
ITERATOR(迭代器)
适用性:
访问一个聚合对象的内容而无需暴露它的内部表示。
支持对聚合对象的多种遍历。
为遍历不同的聚合结构提供一个同一的接口。
思考:
熟悉STL的人看到这个模式应该发出会心一笑,是的,STL的迭代器正是迭代器模式的运用。迭代器总是和聚合联系在一起,提到迭代器,就需要关注两个方面:一是访问谁,二是怎么访问。
对于一个迭代器对象,它需要知道访问的是什么聚合对象,当然这种“知道”并没有固定的方式。一种方式是,在迭代器对象内部记录关联的对象引用,另一种方式是记录迭代器在聚合中所处的位置。STL的迭代器采用的是后一种方法。前一种方法界面简单,而且,有可能有效地对付迭代器失效问题。后一种迭代器更灵活,但是,所有保证正确的责任落在了程序员身上。还有一种内部迭代器,就是把迭代要完成的过程代码作为参数,让一个方法帮助完成迭代过程,这种方式更优雅、简单和安全,但是,也更不灵活。对于C++来说,尤其如此。即使有boost.lambda帮忙,也仍然过于复杂。不过,如果C++支持闭包、嵌套函数,我想也许情况会好一点。
另一个问题是如何访问。迭代器的访问方式一般是预定义的,当然,你也可以设计一个可以定制其访问方式的迭代器来。迭代器并不意味着要访问聚合中的所有元素,也个聚合也可以提供多种迭代器。对于一个树而言,可以提供前序遍历的迭代器,也可以提供中序遍历的迭代器。你也可以为一个线性聚合提供访问奇数元素的迭代器和访问偶数元素的迭代器,虽然我没有想出来这有什么用处。