初识设计模式——解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern)是一种行为设计模式,它定义了一种语言的文法表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。简单来说,就是为了解释一种特定的语言而设计的模式。
解释器模式的构成
- 抽象表达式(Abstract Expression):定义解释操作的抽象接口,具体的解释器类将实现该接口。
- 终结符表达式(Terminal Expression):实现与文法中的终结符相关的解释操作。终结符是语言中不能再分解的基本符号。
- 非终结符表达式(Non - Terminal Expression):实现与文法中的非终结符相关的解释操作。非终结符是- **可以由其他符号(终结符或非终结符)组成的符号。
- 上下文(Context):包含解释器解释时需要的全局信息。
- 客户端(Client):构建表示该语言中某个特定句子的抽象语法树,并调用解释操作。

示例
场景介绍
开发中,经常需要使用配置文件来管理一些经常变化的内容,假定配置文件采用简单的键值对格式,像key = value
这样,并且支持注释(以 # 开头)。我们要实现一个解释器,对配置文件内容进行解析,把键值对提取出来。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| <?php
abstract class ConfigExpression { abstract public function interpret($context); }
class KeyValueExpression extends ConfigExpression { private $key; private $value;
public function __construct($key, $value) { $this->key = $key; $this->value = $value; }
public function interpret($context) { $context[$this->key] = $this->value; return $context; } }
class CommentExpression extends ConfigExpression { public function interpret($context) { return $context; } }
class EmptyLineExpression extends ConfigExpression { public function interpret($context) { return $context; } }
class ConfigContext { private $config = [];
public function getConfig() { return $this->config; }
public function setConfig($config) { $this->config = $config; } }
class ConfigInterpreter { public function parse($lines) { $context = new ConfigContext(); foreach ($lines as $line) { $expression = $this->createExpression($line); $context->setConfig($expression->interpret($context->getConfig())); } return $context->getConfig(); }
private function createExpression($line) { $line = trim($line); if (strpos($line, '#') === 0) { return new CommentExpression(); } elseif (empty($line)) { return new EmptyLineExpression(); } else { list($key, $value) = explode('=', $line, 2); $key = trim($key); $value = trim($value); return new KeyValueExpression($key, $value); } } }
$configFile = 'config.txt'; if (file_exists($configFile)) { $lines = file($configFile, FILE_IGNORE_NEW_LINES); $interpreter = new ConfigInterpreter(); $config = $interpreter->parse($lines);
foreach ($config as $key => $value) { echo "$key: $value\n"; } } else { echo "配置文件未找到。"; } ?>
|
代码含义
- 抽象表达式(ConfigExpression):定义了解释操作的抽象接口 interpret。
- 终结符表达式(KeyValueExpression):对键值对进行解释,将其添加到配置上下文中。
- 非终结符表达式(CommentExpression 和 EmptyLineExpression):分别处理注释和空行,直接返回上下文,忽略这些行。
- 上下文(ConfigContext):用来存储解析后的配置信息。
- 解释器(ConfigInterpreter):读取配置文件的每一行,创建对应的表达式对象,然后调用 interpret 方法进行解释。
UML类图

解释器模式的优缺点
优点
- 可扩展性:可以很容易地添加新的解释器规则,扩展语言的功能。
- 灵活性:可以根据不同的需求,灵活地组合和使用解释器。
- 可维护性:每个解释器类只负责一个特定的解释任务,代码结构清晰,易于维护。
缺点
- 复杂性:对于复杂的文法,解释器模式会导致类的数量急剧增加,使代码变得复杂和难以维护。
- 效率问题:解释器模式通常需要递归调用,对于大规模的输入,会导致性能问题。
解释器模式的常用应用场景
- 编译器:编译器需要对源代码进行词法分析、语法分析和语义分析,解释器模式可以用于实现语法分析阶段,将源代码解析为抽象语法树。
- 正则表达式引擎:正则表达式是一种特定的语言,解释器模式可以用于解释和执行正则表达式。
- SQL 解析器:解析 SQL 语句,将其转换为数据库可以执行的操作。
- 配置文件解析:解析配置文件中的特定语法,例如 XML、JSON 等。