2.7. Facade

2.7.1. Zweck

Das primäre Ziel des Facade-Musters ist nicht, dir das Lesen von komplexen API Dokumentationen zu ersparen. Das kann ein Seiteneffekt sein. Es ist vielmehr das Ziel, Kopplungen zu vermeiden und dem Demeter-Gesetz zu folgen.

Eine Facade dient dazu, den Client von einem Subsystem zu entkopplen, indem ein oder mehrere Interfaces einzuführen und damit Komplexität zu verringern.

  • Eine Facade verbietet nicht den Zugriff auf das Subsystem
  • Es ist nicht unüblich, mehrere Fassaden für ein Subsystem zu implementieren

Deshalb besitzt eine gute Facade keine new Aufrufe. Falls es mehrere Erzeugungsmethoden pro Methode gibt, handelt es sicht nicht um eine Facade, sondern um einen Builder oder [Abstract|Static|Simple] Factory [Method].

Bestenfalls besitzt eine Facade kein new und einen Konstruktor mit Type-Hints als Parameter. Falls du neue Instanzen erzeugen willst, kannst du eine Factory als Argument verwenden.

2.7.2. UML Diagramm

Alt Facade UML Diagram

2.7.3. Code

Du findest den Code auch auf 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
<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade;

class Facade
{
    public function __construct(private Bios $bios, private OperatingSystem $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
11
12
<?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
15
16
<?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. Теst

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
31
32
<?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());
    }
}