2.7. 外观模式¶
2.7.1. 目的¶
The primary goal of a Facade Pattern is not to avoid you having to read the manual of a complex API. It’s only a side-effect. The first goal is to reduce coupling and follow the Law of Demeter.
Facade通过嵌入多个(当然,有时只有一个)接口来解耦访客与子系统,当然也降低复杂度。
- Facade 不会禁止你访问子系统
- 你可以(应该)为一个子系统提供多个 Facade
因此一个好的 Facade 里面不会有 new
。如果每个方法里都要构造多个对象,那么它就不是 Facade,而是生成器或者[抽象|静态|简单] 工厂 [方法]。
优秀的 Facade 不会有 new
,并且构造函数参数是接口类型的。如果你需要创建一个新实例,则在参数中传入一个工厂对象。
2.7.2. UML 图¶

2.7.3. 代码¶
你可以在 GitHub 上找到这些代码
Facade.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 | <?php declare(strict_types=1);
namespace DesignPatterns\Structural\Facade;
class Facade
{
private OperatingSystem $os;
private Bios $bios;
public function __construct(Bios $bios, OperatingSystem $os)
{
$this->bios = $bios;
$this->os = $os;
}
public function turnOn()
{
$this->bios->execute();
$this->bios->waitForKeyPress();
$this->bios->launch($this->os);
}
public function turnOff()
{
$this->os->halt();
$this->bios->powerDown();
}
}
|
OperatingSystem.php
1 2 3 4 5 6 7 8 9 10 | <?php declare(strict_types=1);
namespace DesignPatterns\Structural\Facade;
interface OperatingSystem
{
public function halt();
public function getName(): string;
}
|
Bios.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?php declare(strict_types=1);
namespace DesignPatterns\Structural\Facade;
interface Bios
{
public function execute();
public function waitForKeyPress();
public function launch(OperatingSystem $os);
public function powerDown();
}
|
2.7.4. 测试¶
Tests/FacadeTest.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 | <?php declare(strict_types=1);
namespace DesignPatterns\Structural\Facade\Tests;
use DesignPatterns\Structural\Facade\Bios;
use DesignPatterns\Structural\Facade\Facade;
use DesignPatterns\Structural\Facade\OperatingSystem;
use PHPUnit\Framework\TestCase;
class FacadeTest extends TestCase
{
public function testComputerOn()
{
$os = $this->createMock(OperatingSystem::class);
$os->method('getName')
->will($this->returnValue('Linux'));
$bios = $this->createMock(Bios::class);
$bios->method('launch')
->with($os);
/** @noinspection PhpParamsInspection */
$facade = new Facade($bios, $os);
$facade->turnOn();
$this->assertSame('Linux', $os->getName());
}
}
|