Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; SEOLinks has a deprecated constructor in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 13

Notice: Undefined index: enable-plugin in /home/codigoli/public_html/wp-content/plugins/js-css-script-optimizer/js-css-script-optimizer.php on line 162
Strategy pattern en acción con PHP

Strategy Pattern en acción con PHP


Notice: Undefined index: Archivo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Archivo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Archivo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Sobre mi in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Sobre mi in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Instalando Zend Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Instalando Zend Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Zend Famework 1.6.2 y 1.7.0PR in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Zend Famework 1.6.2 y 1.7.0PR in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: ZF2 Crear un nuevo módulo II in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: ZF2 Crear un nuevo módulo II in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Hola Mundo :: Empezando con ZF2 in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Hola Mundo :: Empezando con ZF2 in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: ZF2 Introducción a los Módulos I in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: ZF2 Introducción a los Módulos I in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Strategy Pattern (Patrón Estrategia) in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Strategy Pattern (Patrón Estrategia) in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Strategy Pattern (Patrón Estrategia) in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Comparación y Rendimiento de Frameworks PHP in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Comparación y Rendimiento de Frameworks PHP in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Proteger nuestros archivos .INI en Zend Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Proteger nuestros archivos .INI en Zend Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Estilo de programación y convención de nombres I in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Estilo de programación y convención de nombres I in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Estilo de programación y convención de nombres II in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: Estilo de programación y convención de nombres II in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 400

Notice: Undefined index: MySql in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: General in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: 97-things in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: JavaScript in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: TypeScript in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Cheat Sheet in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Zend Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Symfony Framework in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Patrones de Diseño in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Programacion Funcional in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Ingeniería de Software in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Patrones de Comportamiento in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Nuevo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: MySql in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: scrum in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: agile in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: scala in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: https://codigolinea.com/tag/scala/ in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 523

Notice: Undefined index: solid in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: elixir in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: amfphp in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: fsharp in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: fechas in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: lambda in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: golang in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: erlang in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: modular in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: haskell in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Closure in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: chuleta in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: testing in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: clojure in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: scalajs in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: modulos in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: reactjs in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Unknown in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: contexto in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: ISO 8601 in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Cake PHP in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: dojo 1.2 in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: 97things in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: software in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: agilismo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: seguridad in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: interfaces in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: desarrollo in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: javascript in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: purescript in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: GET_FORMAT in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: typescript in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: encapsular in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: https://codigolinea.com/tag/encapsular/ in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 523

Notice: Undefined index: manifiesto in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: Zend_Cache in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: estrategia in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 506

Notice: Undefined index: https://codigolinea.com/tag/estrategia/ in /home/codigoli/public_html/wp-content/plugins/seo-automatic-links/seo-links.php on line 523


En el artículo anterior ya hemos visto la definición del Strategy Patern y como se aplica, ahora vamos a ver un ejemplo de la vida real, para eso vamos implementar los métodos de pago que podría tener nuestra tienda virtual.

Contexto

Nuestra pequeña tienda virtual permite que nuestros clientes paguen con tarjeta de crédito, pero como el negocio va creciendo tenemos que adaptarnos al entorno, así que tenemos que implementar otras formas adicionales de pagos como: deposito en cuenta, pago a través de teléfonos móviles, pago contra entrega, cheque, etc.

Cada método de pago tiene una forma distinta de implementarse, ya que cada uno requiere y maneja datos e información distinta, entonces debemos encapsular cada uno de ellos.

Para este ejemplo vamos a implementar el pago con tarjeta de crédito y con PayPal

UML

shoping_cart

Implementación

En primer lugar vamos a crear la interfaz de nuestra estrategia, en nuestro caso, la cantidad que se va pagar lo vamos a pasar como argumento.

// PaymentInterface.php
namespace Behavioral\Strategy\Example\ShoppingCart;

interface PaymentInterface
{
    public function pay($amount);
}

Ahora tendremos que crear las estrategias concretas (algoritmos) para el pago mediante tarjeta de crédito y PayPal.

//CreditCardPayment.php
namespace Behavioral\Strategy\Example\ShoppingCart;

use Behavioral\Strategy\Example\ShoppingCart\PaymentInterface;

class CreditCardPayment implements PaymentInterface
{

    private $name;
    private $cardNumber;
    private $cvv;
    private $dateOfExpiry;

    public function __construct($name, $cardNumber, $cvv, $dateOfExpiry)
    {
        $this->name         = $name;
        $this->cardNumber   = $cardNumber;
        $this->cvv          = $cvv;
        $this->dateOfExpiry = $dateOfExpiry;
    }

    public function pay($amount)
    {
        echo $amount." paid with credit/debit card";
    }
}
//PaypalPayment.php
namespace Behavioral\Strategy\Example\ShoppingCart;

use Behavioral\Strategy\Example\ShoppingCart\PaymentInterface;

class PaypalPayment implements PaymentInterface
{

    private $emailId;
    private $password;

    public function __construct($email, $password)
    {
        $this->emailId              = $email;
        $this->password = $password;
    }

    public function pay($amount)
    {
        echo $amount." paid using Paypal";
    }
}

Ahora nuestras estrategias (algoritmos) están listos y podemos implementar el Carrito de Compras. Observa que el método de pago del Carrito de Compras, requiere el algoritmo de pago como argumento

//ShoppingCart.php
namespace Behavioral\Strategy\Example\ShoppingCart;

use Behavioral\Strategy\Example\ShoppingCart\Item;
use Behavioral\Strategy\Example\ShoppingCart\PaymentInterface;

class ShoppingCart
{

    private $items = [];

    public function addItem(Item $item)
    {
        $this->items[$item->getId()] = $item;
    }

    public function removeItem($itemId)
    {
        if (isset($this->items[$itemId])) {
            unset($this->items[$itemId]);
        }
    }

    public function getItems()
    {
        return $this->items;
    }

    public function calculateTotal()
    {
        $sum = 0;
        foreach ($this->items as $items) {
            $sum += $items->getPrice();
        }
        return $sum;
    }

    public function pay(PaymentInterface $paymentMethod)
    {
        $amount = $this->calculateTotal();
        $paymentMethod->pay($amount);
    }
}

Crearemos una clase Item para almacenar la información de los productos y pasárselo al carrito de compra

//Item.php
namespace Behavioral\Strategy\Example\ShoppingCart;

class Item
{

    private $id;
    private $upcCode;
    private $price;

    public function __construct($id, $upc, $cost)
    {
        $this->id      = $id;
        $this->upcCode = $upc;
        $this->price   = $cost;
    }

    public function getId()
    {
        return $this->id;
    }

    public function getUpcCode()
    {
        return $this->upcCode;
    }

    public function getPrice()
    {
        return $this->price;
    }
}

Vamos a probar como funciona nuestra programa

use Behavioral\Strategy\Example\ShoppingCart\Item;
use Behavioral\Strategy\Example\ShoppingCart\ShoppingCart;
use Behavioral\Strategy\Example\ShoppingCart\CreditCardPayment;
use Behavioral\Strategy\Example\ShoppingCart\PaypalPayment;

$cart = new ShoppingCart();

$item1 = new Item(1, '124', 10);
$item2 = new Item(2, '14', 40);

$cart->addItem($item1);
$cart->addItem($item2);

/** Si mi cliente va usar una tarjeta de crédito, uso esto* */
//Pago con Tarjeta de Crédito
$cart->pay(new CreditCardPayment("Jhon W.", "101012123456", "786", "12/15"));
//El resultado sera:
//50 paid with credit/debit card

/** Si mi cliente va usar su cuenta paypal uso esto* */
//Pago con Paypal
$cart->pay(new PaypalPayment("my_email@example.com", "my_password"));
//El resultado sera:
//50 paid using Paypal

De esa manera podemos agregar muchas mas formas de pago sin necesidad de tocar las demás clases haciendo mas flexible nuestro programa.

¿Sencillo no?

Los archivos lo puedes encontrar en en el siguiente enlace:
https://github.com/benjamingb/DesignPatternsPHP/tree/master/Behavioral/Strategy

benjamin
Me llamo Benjamín Gonzales B, soy desarrollador de software con más de 15 años de experiencia, socio funduador de la empresa GNBIT. Me apasiona todo lo relacionado a las nuevas tecnologías, me gusta investigar , leer y aprender cada día algo nuevo. Desarrollo en PHP7+, JAVA, C#, JavaScript, entre otros y actualmente  estoy experimentando con lenguajes funcionales como: Erlang, Clojure y Scala 

6 Comments

    1. Hola Jorge
      La estrategia que vas usar es según tu contexto, esto quiere decir que si viene un cliente a tu tienda virtual y desea pagar con una tarjeta de crédito (contexto) ya tienes preparada un algoritmo que procesa la tarjeta de crédito (estrategia), si otro cliente desea pagar con un cheque ya tienes preparada otro algoritmo para procesar un cheque.

      Aquí hay una explicación mas amplia sobre este patrón Strategy Pattern

      Recuerda que por lo general es una estrategia para un contexto, cambia de contexto cambia de estrategia.

      Espero haberte ayudado

      Saludos!

    2. Creo que la pregunta de Jorge es , porque no usatse un if o switch para llamar a $cart->pay

      Si no que llamste a ambas funciones sin cambiar o filtrar el contexto

      1. Hola Daniel
        El objetivo del ejemplo era mostrar las formas distintas de llamarlo, y eso lo puse en los comentarios, pero tienes razón, creo que poniendo un if hubiese quedado mas claro.
        Gracias

  1. El ejemplo tira mas para FactoryMethod que Strategy. Hubieras puesto como ejemplo:

    – Si el monto a pagar es mayor a X, usar tarjeta, si no, cambias de estrategia y pagas con paypal

Leave a Comment

Su dirección de correo no se hará público. Los campos requeridos están marcados *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.