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<?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. Теst

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}