Design Patterns – Facade

Sometimes our programs become too complex and some objects are being difficult to use and many times these processes for being using an object are repetitive and almost the same. In these cases, we can provide a Facade and with it, we are able to hide unnecessary processes and provide to our users only what they want to use, avoiding repetitive instructions and being a facilitator.

This structural pattern helps to decouple subsystems and is heavily used in frameworks and as well in many libraries, it helps developers to keep the system more simple and could be used as well as an anticorruption layer and also could be implemented as Singleton.

It describes how to represent complex subsystems in only one place.


Intent

Provides a simplified interface to a library, a framework, or any other complex set of classes (Subsystems). It defines a high level of programming making easy-to-use subsystems.


Diagram

  • Facade -> Class that has knowlodge about other complex systems and will be the facilitator for other programmers.
  • Complex subsystems -> Classes that our Facade will simplify for us.

“Real World” Example

Well, let’s imagine that we need to work with queues but our library has a process a bit more difficult than what we are expecting and we also could be changing this library in a few months because our manager doesn’t make a decision yet which service we will use.

Seems a good real example of where to apply Facade Design Pattern. We could use this same idea when need to work with Cache, Notifications.


First, let’s add the right folders and files to our project, and it should be like this.

. designpatterns
.. src
... Structural
.... Facade
..... QueueExample
...... ComplexSubsystem
...... Contracts
.. tests
... Structural
.... Facade
..... QueueExample

Let’s code

First, we will create a simple Contract for our Message, inside our Contracts folder we need to create this file:

MessageInterface.php

<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade\QueueExample\Contracts;

interface MessageInterface
{
    public function getPayload(): string;
}

Now we’ll implement a fake complex subsystem (I know our example is simple, but you got the idea) using 3 classes just to help us show the idea of how Facade could facilitate our job. Inside ComplexSubsystem folder we have to create three files as below:

QueueMessage.php

<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem;

use DesignPatterns\Structural\Facade\QueueExample\Contracts\MessageInterface;

class QueueMessage implements MessageInterface
{
    public function __construct(private string $payload)
    {
    }

    public function getPayload(): string
    {
        return $this->payload;
    }
}

QueueConnection.php

<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem;

class QueueConnection
{
    private string $status;
    private string $connection;

    public const CONNECTION_OPENED = 'opened';
    public const CONNECTION_CLOSED = 'closed';

    public function __construct(private string $host, private int $port)
    {
        $this->connect($this->host, $this->port);
    }

    public function connect(string $host, int $port): void
    {
        $this->status = self::CONNECTION_OPENED;
    }

    public function send(string $payload): string
    {
        return $payload;
    }

    public function close(): void
    {
        $this->status = self::CONNECTION_CLOSED;
    }

    public function getStatus(): string
    {
        return $this->status;
    }
}

QueueChannel.php

<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem;

class QueueChannel
{
    public function __construct(private QueueConnection $connection, public string $channel)
    {
    }

    public function getConnection(): QueueConnection
    {
        return $this->connection;
    }

    public function send(QueueMessage $message): string
    {
        return $this->connection->send($message->getPayload());
    }
}

QueueFacade.php

Now, the Facade, our icing on the cake!

<?php

declare(strict_types=1);

namespace DesignPatterns\Structural\Facade\QueueExample;

use DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem\QueueChannel;
use DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem\QueueConnection;
use DesignPatterns\Structural\Facade\QueueExample\ComplexSubsystem\QueueMessage;

class QueueFacade
{
    private QueueConnection $connection;

    public function __construct()
    {
        $this->connection = new QueueConnection('localhost', 12345);
    }

    public function sendMessage(string $channel, string $message): string
    {
        $channel = new QueueChannel($this->connection, $channel);

        $message = $channel->send(
            new QueueMessage($message)
        );

        $this->connection->close();

        return $message;
    }
}

As we discussed before, the main idea here is to simplify the process of sending a message, with Facade we don’t have to always create a new connection, set the channel, and then send the message. We could simplify this process and provide to other users only what they need to know, in this example is just:

$facade = new Facade();
$facade->sendMessage('My Channel', 'My message payload');

Before finishing this we need to create our test to make sure that everything is working as expected.

As we know, we need to create the QueueExampleTest on our tests/Structural/Facade/QueueExample folder.

QueueExampleTest.php

<?php

declare(strict_types=1);

namespace Tests\Structural\Facade\QueueExample;

use DesignPatterns\Structural\Facade\QueueExample\QueueFacade;
use PHPUnit\Framework\TestCase;

class QueueExampleTest extends TestCase
{
    public function testItCanSendMessage()
    {
        $queue = new QueueFacade();

        $message = $queue->sendMessage('My Channel', 'Message payload');

        $this->assertEquals('Message payload', $message);
    }
}

You can follow our repository https://github.com/diegosm/designpatterns, everything is there.

I hope you understood this concept and feel free to ask something or do your contribution. There are many examples on the internet of this pattern.

This article is a part of our Design Pattern Series, follow our Design Patterns – What, when, why? link 🙂

1 Trackback or Pingback

Leave a Reply

Your email address will not be published. Required fields are marked *




Enter Captcha Here :