Patrones de Diseño

El Patrón de Diseño Strategy define una familia de algoritmos, encapsula cada uno y los hace intercambiables a través del uso de polimorfismo, en este breve artículo te proporcionaremos una introducción a este patrón de diseño y cómo usarlo.


En Laravel tenemos una clase para enviar emails que utiliza diferentes mecanismos o «transportes»; puedes enviar un correo vía SMTP, a través de Mailgun o incluso guardar correos en un archivo de log.

Pero si revisas el código de la clase Mailer no encontrarás esto:

<?php

class Mailer
{
    public function send($email)
    {
        switch ($this->transport) {
            case 'smtp':
                return $this->sendUsingSmtp($email);
            case 'mailgun':
                return $this->sendWithMailgun($email);
            case 'log':
                return $this->logToAFile($email);
        }
    }
}

Porque elegir la manera de enviar correos usando condicionales haría el código difícil de cambiar, además cada método de envío requiere de información o clases extra (por ejemplo, un token o la clase Logger), lo cual terminaría por complicar la clase Mailer con muchos métodos e información no relacionada entre sí.

Por el contrario, lo que hace Laravel o, mejor dicho, SwiftMailer, es definir una serie de transportes cada uno como una clase diferente y todos con la misma interfaz Transport. Al instanciar un objeto de la clase Mailer simplemente debes pasar el transporte que quieras usar, por ejemplo en local quizás quieras guardar en un log:

<?php

$mailer = new Mailer(new LogTransport('storage/log.txt'));

Pero en producción enviar vía SMTP:

<?php

$mailer = new Mailer(new SmtpTransport($credenciales));

A partir de aquí el transporte usado resulta transparente:

<?php

$mailer->send($email);

Aunque, por supuesto, $mailer delegará el envío al transporte usado:

class Mailer
{
    public function send($email)
    {
        return $this->transport->send($email);
    }
}

Nota que los condicionales han desaparecido, crear un nuevo «mecanismo de transporte» para enviar correos es tan sencillo como crear una nueva clase que extienda o implemente Transport y pasarla a la clase Mailer. Incluso podrías usar los transportes en otras clases sin problema:

<?php

new CampaignMailer(new MailChimpTransport($credentials));
new BulkMailer(new MailgunTransport);

Lo cual sería muy difícil o engorroso de lograr utilizando sólo condicionales o herencia, puesto que con esta última técnica terminaríamos con muchas clases y código duplicado.

Este artículo es un pequeño ejemplo y resumen de lo aprendido sobre el Patrón Strategy en nuestro Curso de Patrones de Diseño con PHP.

Material Relacionado

Regístrate hoy en Styde y obtén acceso a todo nuestro contenido.