2.7. Fasada (Facade)
2.7.1. Przeznaczenie
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.
Fasada pozwala oddzielić klienta od podsystemu, poprzez udostępnienie jednego lub wielu interfejsów oraz zredukować złożoność rozwiązania.
Fasada nie zabrania bezpośredniego dostępu do podsystemu.
Dobrym pomysłem jest posiadanie wielu fasad do jednego podsystemu.
Dlatego dobra fasada nie tworzy nowych obiektów, tylko korzysta z istniejących (nie używa operatora new
). Jeżeli w ramach fasady tworzymy wiele obiektów, w ramach każdej metody, wtedy nie mamy do czynienia z Fasadą, tylko z Budowniczym lub formą Fabryki.
W ramach Fasady najlepiej nie używać operatora new
oraz definiować typy argumentów konstruktora (type-hinting). Jeżeli potrzebujemy stworzyć nowe obiekty, powinniśmy przekazać Fabrykę jako argument.
2.7.2. Diagram UML
2.7.3. Kod
Ten kod znajdziesz również na GitHub.
Facade.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\Facade;
6
7class Facade
8{
9 public function __construct(private Bios $bios, private OperatingSystem $os)
10 {
11 }
12
13 public function turnOn()
14 {
15 $this->bios->execute();
16 $this->bios->waitForKeyPress();
17 $this->bios->launch($this->os);
18 }
19
20 public function turnOff()
21 {
22 $this->os->halt();
23 $this->bios->powerDown();
24 }
25}
OperatingSystem.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\Facade;
6
7interface OperatingSystem
8{
9 public function halt();
10
11 public function getName(): string;
12}
Bios.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\Facade;
6
7interface Bios
8{
9 public function execute();
10
11 public function waitForKeyPress();
12
13 public function launch(OperatingSystem $os);
14
15 public function powerDown();
16}
2.7.4. Testy
Tests/FacadeTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace DesignPatterns\Structural\Facade\Tests;
6
7use DesignPatterns\Structural\Facade\Bios;
8use DesignPatterns\Structural\Facade\Facade;
9use DesignPatterns\Structural\Facade\OperatingSystem;
10use PHPUnit\Framework\TestCase;
11
12class FacadeTest extends TestCase
13{
14 public function testComputerOn()
15 {
16 $os = $this->createMock(OperatingSystem::class);
17
18 $os->method('getName')
19 ->will($this->returnValue('Linux'));
20
21 $bios = $this->createMock(Bios::class);
22
23 $bios->method('launch')
24 ->with($os);
25
26 /** @noinspection PhpParamsInspection */
27 $facade = new Facade($bios, $os);
28 $facade->turnOn();
29
30 $this->assertSame('Linux', $os->getName());
31 }
32}