解释器模式 - Interpreter Pattern
定义
定义一个语言的文法,并且建立一个解释器来解释该语言中的句子。
设计的原则和思想
- 解耦的是需要解释的内容和解释文法的方式。
- 不变部分是解释文法的方式,变化部分是需要解释的内容。
- 核心思想是将语法解析拆分到最小单元,然后按照某种文法规则重新组合。
一句话概括设计模式
用一种类似抽象语法树的表达式去解释一种语言。
终结符和非终结符
终结符
它们是语言的最小组成单位,不能拆分的最小元素。在英文里面终结符是字母。
非终结符
它们都是一个完整的句子,包含一系列终结符或非终结符。在英文里面非终结符是句子或者单词。
结构中包含的角色
- AbstractExpression(抽象表达式)
- TerminalExpression(终结符表达式)
- NonterminalExpression(非终结符表达式)
- Context(环境类)
最小可表达代码
// 抽象表达式
abstract class AbstractExpression
{
public abstract function interpret();
}
// 终结符表达式
class FigureTerminalExpression extends AbstractExpression
{
private $figure;
public function __construct($figure)
{
$this->figure = $figure;
}
public function interpret()
{
return $this->figure;
}
}
// 非终结符表达式
class AddNonterminalExpression extends AbstractExpression
{
private $left;
private $right;
public function __construct(AbstractExpression $left, AbstractExpression $right)
{
$this->left = $left;
$this->right = $right;
}
public function interpret()
{
return $this->left->interpret() + $this->right->interpret();
}
}
// 环境类
class Context
{
private $sentence;
public function setSentence(String $sentence)
{
$this->sentence = $sentence;
}
public function calculate()
{
$symbols = [];
$expressions = [];
foreach (explode(' ', $this->sentence) as $char) {
if (is_numeric($char)) {
$expressions[] = new FigureTerminalExpression($char);
} else {
$symbols[] = $char;
}
}
foreach ($symbols as $symbol) {
if ('+' == $symbol) {
$left = array_pop($expressions);
$right = array_pop($expressions);
$expression = (new AddNonterminalExpression($left, $right));
array_unshift($expressions, $expression);
continue;
}
}
return array_pop($expressions)->interpret();
}
}
$context = new Context();
$sentence = '1 + 1';
$context->setSentence($sentence);
var_dump($context->calculate());
优点
- 增加了新的解释表达式的方式。
- 易于实现简单文法。每一条文法规则都可以表示为一个类,可以方便地实现一个简单的语言。
- 容易实现,改变和扩展文法。
- 增加新的解释表达式较为方便。增加一个新的终结符表达式或非终结符表达式类即可。
缺点
- 可利用场景比较少。
- 对于复杂的文法比较难维护。
- 解释器模式会引起类膨胀。
- 解释器模式中使用了大量的循环和递归调用,执行效率较低。
何时使用
- 一些问题可以用简单的语言来表达,并且不关注执行效率的。
- 可以将一个需要解释的语言句子表示为一个抽象语法树。
实际应用场景
- sql解析。
- 正则表达式。
- Google Translate 这样的翻译器。