流式接口模式

目的

让书写代码像使用自然语言(如:英语)书写句子一样容易阅读。

使用场景

  • Doctrine2 的查询构造器的工作原理类似于下面例子中的 Sql
  • PHPUnit 使用流式接口来创建模拟对象

UML 类图

流式接口模式类图

代码

Sql.php

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
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\FluentInterface;

class Sql
{
private array $fields = [];
private array $from = [];
private array $where = [];

public function select(array $fields): Sql
{
$this->fields = $fields;

return $this;
}

public function from(string $table, string $alias): Sql
{
$this->from[] = $table.' AS '.$alias;

return $this;
}

public function where(string $condition): Sql
{
$this->where[] = $condition;

return $this;
}

public function __toString(): string
{
return sprintf(
'SELECT %s FROM %s WHERE %s',
join(', ', $this->fields),
join(', ', $this->from),
join(' AND ', $this->where)
);
}
}

测试

Tests/FluentInterfaceTest.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php declare(strict_types = 1);

namespace DesignPatterns\Extend\FluentInterface\Tests;

use DesignPatterns\Extend\FluentInterface\Sql;
use PHPUnit\Framework\TestCase;

class FluentInterfaceTest extends TestCase
{
public function testBuildSQL()
{
$query = (new Sql())
->select(['foo', 'bar'])
->from('foobar', 'f')
->where('f.bar = ?');

$this->assertSame('SELECT foo, bar FROM foobar AS f WHERE f.bar = ?', (string) $query);
}
}