3.3. 解释器模式
3.3.1. 目的
对于给定的语言,它定义了其语法的表示为【非终结符表达式】和【终结符达式】,以及改语言的句子解释器。
3.3.2. 例子
一个二进制逻辑解释器的例子,每个定义都是由它自己的类定义的
3.3.3. UML 图

3.3.4. 代码
在 GitHub 上查看代码
AbstractExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7abstract class AbstractExp
8{
9 abstract public function interpret(Context $context): bool;
10}
Context.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7use Exception;
8
9class Context
10{
11 private array $poolVariable;
12
13 public function lookUp(string $name): bool
14 {
15 if (!key_exists($name, $this->poolVariable)) {
16 throw new Exception("no exist variable: $name");
17 }
18
19 return $this->poolVariable[$name];
20 }
21
22 public function assign(VariableExp $variable, bool $val)
23 {
24 $this->poolVariable[$variable->getName()] = $val;
25 }
26}
VariableExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This TerminalExpression
9 */
10class VariableExp extends AbstractExp
11{
12 public function __construct(private string $name)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $context->lookUp($this->name);
19 }
20
21 public function getName(): string
22 {
23 return $this->name;
24 }
25}
AndExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This NoTerminalExpression
9 */
10class AndExp extends AbstractExp
11{
12 public function __construct(private AbstractExp $first, private AbstractExp $second)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $this->first->interpret($context) && $this->second->interpret($context);
19 }
20}
OrExp.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter;
6
7/**
8 * This NoTerminalExpression
9 */
10class OrExp extends AbstractExp
11{
12 public function __construct(private AbstractExp $first, private AbstractExp $second)
13 {
14 }
15
16 public function interpret(Context $context): bool
17 {
18 return $this->first->interpret($context) || $this->second->interpret($context);
19 }
20}
3.3.5. 测试
Tests/InterpreterTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Behavioral\Interpreter\Tests;
6
7use DesignPatterns\Behavioral\Interpreter\AndExp;
8use DesignPatterns\Behavioral\Interpreter\Context;
9use DesignPatterns\Behavioral\Interpreter\OrExp;
10use DesignPatterns\Behavioral\Interpreter\VariableExp;
11use PHPUnit\Framework\TestCase;
12
13class InterpreterTest extends TestCase
14{
15 private Context $context;
16 private VariableExp $a;
17 private VariableExp $b;
18 private VariableExp $c;
19
20 public function setUp(): void
21 {
22 $this->context = new Context();
23 $this->a = new VariableExp('A');
24 $this->b = new VariableExp('B');
25 $this->c = new VariableExp('C');
26 }
27
28 public function testOr()
29 {
30 $this->context->assign($this->a, false);
31 $this->context->assign($this->b, false);
32 $this->context->assign($this->c, true);
33
34 // A ∨ B
35 $exp1 = new OrExp($this->a, $this->b);
36 $result1 = $exp1->interpret($this->context);
37
38 $this->assertFalse($result1, 'A ∨ B must false');
39
40 // $exp1 ∨ C
41 $exp2 = new OrExp($exp1, $this->c);
42 $result2 = $exp2->interpret($this->context);
43
44 $this->assertTrue($result2, '(A ∨ B) ∨ C must true');
45 }
46
47 public function testAnd()
48 {
49 $this->context->assign($this->a, true);
50 $this->context->assign($this->b, true);
51 $this->context->assign($this->c, false);
52
53 // A ∧ B
54 $exp1 = new AndExp($this->a, $this->b);
55 $result1 = $exp1->interpret($this->context);
56
57 $this->assertTrue($result1, 'A ∧ B must true');
58
59 // $exp1 ∧ C
60 $exp2 = new AndExp($exp1, $this->c);
61 $result2 = $exp2->interpret($this->context);
62
63 $this->assertFalse($result2, '(A ∧ B) ∧ C must false');
64 }
65}