2.7. Facade

2.7.1. Propósito

El objetivo principal del Patrón Facade (o Patrón Fachada) no es evitar que tenga que leer el manual de una compleja API. Es solo un efecto secundario. El primer objetivo es reducir el acoplamiento y seguir la Ley de Demeter.

Una Fachada está destinada a desacoplar un cliente y un subsistema al incorporar muchas (pero a veces solo una) interfaz y, por supuesto, reducir la complejidad.

  • Una fachada no le prohíbe el acceso al subsistema

  • Puede (debería) tener múltiples fachadas para un subsistema

Por eso una buena fachada no tiene new en ella. Si hay varias creaciones para cada método, no es una fachada, es un Builder (Constructor) o una [Abstract|Static|Simple] Factory [Method].

La mejor fachada no tiene new y un constructor con parámetros interfaz-type-hinted. Si necesita crear nuevas instancias, utilice Factory como argumento.

2.7.2. Diagrama UML

Alt Facade UML Diagram

2.7.3. Código

Puedes encontrar el código en 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. Test

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}