2.7. Facade

2.7.1. Amaç

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.

Bir önyüz, bir veya birden fazla arayüzü gömerek (interface injection) bir istemci ve bir alt sistemi ayrıştırmak ve tabii ki karmaşıklığı azaltmak içindir.

  • Bir önyüz alt sisteme erişimi yasaklamaz.
  • Bir alt sistem için birden fazla önyüze sahip olabilirsiniz (olmalısınız).

İyi tasarlamış bir önyüzde new diye bir şey olmamasının nedeni budur. Her yöntem için birden fazla oluşturum varsa (multiple creation), bu artık bir Önyüz değil, bir Yapıcı (Builder) ya da [Soyut (Abstract)|Statik (Static)|Basit (Simple)] Fabrika (Factory) [Yöntem (Method)] olur.

En iyi önyüz new içermeyen ve kurucusu (constructor) arayüz türü ipuçlanarak (interface-type-hinted) parametrize edilmiş olandır. Şayet yeni örnekler (instance) oluşturmanız gerekiyorsa, argüman olarak bir Fabrika (Factory) kullanın.

2.7.2. UML Diyagramı

Alt Facade UML Diagram

2.7.3. Kod

Bu kodu Github üzerinde de bulabilirsiniz.

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. Test

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