Thiago Cantero

Tecnologia e Entretenimento

Arquitetura de SoftwareDesenvolvimento WebFacadePadrões de ProjetoPHPProgramação

Design Patterns – Facade em PHP

Olá, mundo!
Tudo bem?

No post de hoje, venho exemplificar o padrão Facade que atua como simplificador de serviços ou API complexas, servindo de uma interface para implementação da classe em sua aplicação.

Vamos a sua definição segundo a Obra dos Integrantes da GoF:

Fornecer uma interface unificada para um conjunto de interfaces em um subsistema.
Façade define uma interface de nível mais alto que torna o subsistema mais fácil de  ser usado.
Estruturar um sistema em subsistemas ajuda a reduzir a complexidade. Um objetivo comum de todos os projetos é minimizar a comunicação e as dependências entre subsistemas. Uma maneira de atingir esse objetivo é introduzir um objeto facade (fachada), o qual fornece uma interface única e simplificada para os recursos e facilidades mais gerais de um subsistema. Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos, pág. 179, Editora Bookman 2008.

UML do Padrão Facade – Obtido na Wikipedia – disponível em: https://en.wikipedia.org/wiki/Facade_pattern#/media/File:Example_of_Facade_design_pattern_in_UML.png

Como podemos observar, ele serve como uma camada de abstração, deixando menos complexo classes de serviços diversos que podem ser implementados em sua aplicação. Então, com estes breves conceitos fixados, vamos ver como isso funciona?

Vamos ao Trabalho//

Imagine que sua aplicação tenha uma rotina em que realiza a conversão de arquivo de vídeo MP4 para AVI (vice-versa), isso foge um pouco dos padrões de aplicações web, concorda?Dada a complexidade de se alterar compressões de vídeo. No entanto chamaremos a API ou biblioteca que faça isso, e apresentar em nossa aplicação através do Padrão Facade.

O código será com o padrão PSR-4 do PHP, então vamos criar conforme segue:

Como adotamos o padrão de código acima, iremos criar uma subpasta “src” e logo após, na raiz criamos o arquivo abaixo:

composer.json

{ "autoload":
    { "psr-4":
        { 
        "DesignPatterns\\": "src/" 
        } 
    } 
}

Agora iremos criar a Classe  Facade que fará a implementação de nosso conversor de vídeo:

/src/FacadePattern.php

<?php
/**   
 * Facade Pattern 
 * @version 1.0   
 * @package Facade
 * @subpackage FacadePattern  
 * @author Thiago Cantero Mari Monteiro   
 * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro   
 * @license http://www.thiagocantero.com.br/sobre  
 **/

namespace DesignPatterns;

use DesignPatterns\ConversorMP4;
use DesignPatterns\ConversorAVI;


class FacadePattern
{
    protected $ConversorMP4;

    protected $ConversorAVI;

    /**
     * Método Construtor dos Objetos
    */
    public function __construct(
        ConversorMP4 $ConversorMP4 = null,
        ConversorAVI $ConversorAVI = null
    ) {
        $this->ConversorMP4 = $ConversorMP4 ?: new ConversorMP4();
        $this->ConversorAVI = $ConversorAVI ?: new ConversorAVI();
    }

    /**
     * Os métodos do Padrão Facade atuarão como atalhos para sofisticados
     * serviços, APIs, ou uma classe de serviço complexa, tornando o código
     * mais limpo e eficiente.
    */
    public function conversao(): string
    {
        $resultado = "Facade initializa as classes de API ou Serviços:\n";
        $resultado .= $this->ConversorMP4->conversao1();
        $resultado .= $this->ConversorAVI->conversao2();
        $resultado .= "Facade realiza a ação de Conversão dos Arquivos:\n";
        $resultado .= $this->ConversorMP4->conversaoMP4();
        $resultado .= $this->ConversorAVI->conversaoAVI();

        return $resultado;
    }
}

Agora faremos nossas classes de Serviços de Conversão, MP4 e AVI, respectivamente:

/src/ConversorMP4.php

<?php
/**   
 * Facade Pattern 
 * @version 1.0   
 * @package ConversorMP4
 * @subpackage FacadePattern  
 * @author Thiago Cantero Mari Monteiro   
 * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro   
 * @license http://www.thiagocantero.com.br/sobre  
 **/

namespace DesignPatterns;

class ConversorMP4
{
    public function conversao1(): string
    {
        return "Conversão1: Arquivo enviado para converter ao formato MP4!\n";
    }

    // ...

    public function conversaoMP4(): string
    {
        return "Conversão para MP4: Finalizado!\n";
    }
}

/src/ConversorAVI.php

<?php
/**   
 * Facade Pattern 
 * @version 1.0   
 * @package ConversorAVI
 * @subpackage FacadePattern  
 * @author Thiago Cantero Mari Monteiro   
 * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro   
 * @license http://www.thiagocantero.com.br/sobre  
 **/

namespace DesignPatterns;

class ConversorAVI
{
    public function conversao2(): string
    {
        return "Conversão2: Arquivo enviado para converter ao formato AVI!\n";
    }

    // ...

    public function conversaoAVI(): string
    {
        return "Conversão para AVI: Finalizado!\n";
    }
}

E por fim nossa Entrypoint na pasta Raiz:

Index.php

<?php
/**   
 * Facade Pattern 
 * @version 1.0   
 * @package Index
 * @subpackage FacadePattern  
 * @author Thiago Cantero Mari Monteiro   
 * @copyright Copyright (c) 2022 Thiago Cantero Mari Monteiro   
 * @license http://www.thiagocantero.com.br/sobre  
 **/

require_once("vendor/autoload.php");

use DesignPatterns\ConversorAVI;
use DesignPatterns\ConversorMP4;
use DesignPatterns\FacadePattern;

function ConversaoFacade(FacadePattern $facade)
{
    

    echo $facade->conversao();

    
}

/**
 * Nossa Entrypoint de implementação do Facade, serve apenas para criarmos e instaciamos os objetos
 * para realizar as suas respectivas complexidades, isto fica a cargo do Padrão Facade.
 */
$ConversorMP4 = new ConversorMP4();
$ConversorAVI = new ConversorAVI();
$facade = new FacadePattern($ConversorMP4, $ConversorAVI);
ConversaoFacade($facade);

Feito toda esta codificação, iremos mapear nossas classes e namespaces com o composer:

composer dump-autoload -o

agora vamos executar nossa aplicação:

Espero que tenha ficado esclarecido como podemos refatorar o código, provendo mais qualidade, produtividade e uma melhor estrutura aos projetos, seja qual for sua necessidade.
Obrigado ; )

Código completo no Github.

Que haja uma luz nos lugares mais escuros, quando todas as outras luzes se apagarem.”