2.7. Facade (Fachada)

2.7.1. Objetivo

O principal objetivo de um Facade Pattern não é evitar que você tenha que ler o manual de uma API complexa. É apenas um efeito colateral. O primeiro objetivo é reduzir o acoplamento e seguir a Lei de Demeter.

Uma Facade destina-se a dissociar um cliente e um subsistema, incorporando muitas (porém as vezes apenas uma) interface e, é claro, para reduzir a complexidade.

  • Uma Facade não proibe você de acessar o sub-sistema

  • Você pode (você deve) ter múltiplas facades para um sub-sistema

É por isso que uma boa facade não tem nenhum new nela. Se há multiplas criações para cada método, ela não é uma facade, ela é uma Builder (Construtora) ou uma [Abstract|Static|Simple] Factory (Fábrica) [Method].

A melhor facade não tem nenhum new e um construtor com parâmetros interface-type-hinted. Se você precisa da criação de novas instâncias, use uma Factory (Fábrica) como argumento.

2.7.2. Diagrama UML

Alt Facade UML Diagram

2.7.3. Código

Você também pode encontrar este código no 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. Teste

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}