Thiago Cantero

Tecnologia e Entretenimento

Arquitetura de SoftwareDesenvolvimento WebPadrões de ProjetoPHPProgramaçãoStrategy

Design Patterns – Strategy em PHP

Olá, Mundo!
Tudo bem?

Imagine que você tem em sua aplicação uma Classe que gera Logs (registros) e estes devem ser salvos em arquivo ou no banco de dados. Como eu faria para que isso fosse, de maneira que eu separasse as responsabilidades de cada função (Registrar em Arquivo/Registrar no Banco de Dados), para que a manutenção do código, e por consequência, a organização fique muito mais eficiente?

Iremos usar o Princípio de Liskov, que visa a Responsabilidade Única de cada função que por ventura tenha no seu código, isso o deixa com um melhor aproveitamento e a possibilidade de agregar uma nova funcionalidade sem muitos problemas. Em nosso exemplo adotaremos a PSR-4 do PHP.

Vamos ao Trabalho\\

Bom, primeiro vamos entender, com um pouco mais de profundidade o Padrão Strategy.

Definir uma família de algoritmos, encapsular cada uma delas e torná-las intercambiáveis. Strategy permite que o algoritmo varie independentemente dos clientes que o utilizam. Padrões de Projeto: Soluções reutilizáveis de software orientado a objetos, pág. 292, Editora Bookman 2008

Ficou bem claro a intenção deste Padrão, não é mesmo? Então, vamos a UML que a Define, e posterior, vamos ao código.

UML – Obtido no Wikipedia. Disponível em: https://en.wikipedia.org/wiki/Strategy_pattern#/media/File:W3sDesign_Strategy_Design_Pattern_UML.jpg

Como podemos observar, há um contexto que no nosso caso, será nosso arquivo Index.php que retornará com as saídas,  em amarelo estão o Strategy 1 e Strategy 2, que nada mais são que as classes com responsabilidade única que falei acima.

Para que isso fique bem claro, vamos ao código!

Primeiro vamos nosso arquivo composer.json.

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

Feito isso vamos criar a subpasta “src” em nosso projeto, nele colocaremos as Classes InterfaceLogger, LogParaArquivo e LogParaBancoDados.

Vamos começar pela nossa Interface que servirá como uma ponte entre as outras duas Classes que terão suas responsabilidades.

InterfaceLogger.php

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

namespace DesignPatterns;

 interface InterfaceLogger {
    
    public function log($data);

}

Agora vamos, na sequência realizar nossas duas classes distintas que cada qual fará o registro em um arquivo, e o registro no banco de dados, respectivamente:

LogParaArquivo.php

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

 namespace DesignPatterns;
 use DesignPatterns\InterfaceLogger;


class LogParaArquivo implements InterfaceLogger {

    public function log($data) {
        var_dump("O Log foi registrado em um arquivo!");
    }

}

LogParaBancoDados.php

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

 namespace DesignPatterns;
 use DesignPatterns\InterfaceLogger;


class LogParaBancoDados implements InterfaceLogger {

    public function log($data) {
        var_dump("O Log foi registrado no Banco de Dados!");
    }

}

E por fim, vamos para nosso arquivo Index.php que será nossa classe principal que consumirá as demais funcionalidades.

Index.php

<?php
/**   
 * Strategy Pattern 
 * @version 1.0   
 * @package Index
 * @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\InterfaceLogger;
use DesignPatterns\LogParaArquivo;
use DesignPatterns\LogParaBancoDados;

class Index {

    public function log($data, InterfaceLogger $logger) {         
        $logger = $logger ?: new LogParaArquivo;
        $logger->log($data);
    }

}

$app = new Index();
$app->log("Log", new LogParaArquivo);
$app->log("Log", new LogParaBancoDados);

Por fim vamos executar a criação de nosso Autoloader através do Composer, para que as Namespaces funcionam de acordo.

composer dump-autoload -o

 

Pronto, agora vamos executar nosso arquivo:

php Index.php

Importante enfatizar que o artigo é apenas uma forma de demonstrar como funciona o Padrão Strategy, ele é muito útil para que possamos dar novas funcionalidades ao Sistema, que por ventura estamos desenvolvendo/melhorando, e tenhamos um controle total dos processos que podem se tornar complexos, no entanto de maneira muito mais organizado.

Boa Viagem! ; )

Código fonte no Github.

Mas a sabedoria que vem do alto é, em primeiro lugar, pura, depois pacífica, moderada, tratável, cheia de misericórdia e de bons frutos, imparcial e sem hipocrisia.

Tiago 3:17.