POO: Inyección de dependencias

Los juegos de estrategia y de rol me ayudaron a entender la programación orientada a objetos y ciertos patrones de diseño. En Warcraft cada unidad (ej: un arquero) es un objeto que interactúa con otras unidades (objetos), el mapa en sí es un objeto que encapsula todos los objetos anteriores.

Una barraca es también un objeto que implementa el patrón Factory porque “produce” otros objetos (soldados). Un héroe podría implementar el patrón “singleton” dado que es único en cada partida.

Así que para aprender fácilmente qué es la inyección de dependencias imaginemos que estamos construyendo el backend de un juego:

Código :

<?php

class Bow {
// Code here
}

class Elf extends Unit {
    protected $bow

    public function __construct()
    {
        $this->bow = new Bow;
    }

    public function shoot($target)
    {
        return $this->bow->shoot($target);
    }
}

class Orc extends Unit {
    //Code here
}

$elf = new Elf;
$elf->setName('Legolas');

$orc = new Orc;

$elf->shoot($orc);

Cada elfo es un objeto que tiene una dependencia en otro objeto (en este caso un arco), además, a medida que el elfo aumente de nivel necesitará de otros arcos más potentes.

¿Con nuestro código actual cómo podemos hacer eso? Respuesta: no podemos. Nuestro heroe está “atado” a usar un sólo tipo de arco y a medida que sus enemigos se vuelvan más fuertes y numerosos no podrá contra ellos y morirá, y será tu culpa.

Inyección de dependencias al rescate

Refactoricemos:

Código :

<?php

interface BowInterface {
    public function shoot($target);
}

class Bow implements BowInterface {
    public function shoot($target)
    {
        // I don't know how to shoot arrows with PHP yet
    }
}

class Elf extends Unit {
    protected $bow

    /**
     * Dependency injection using the class constructor
     */
    public function __construct(BowInterface $bow = null)
    {
    if (is_null($bow))
    {
       $this->bow = new Bow;
    }
    else
    {
        $this->bow = $bow;
    }
    }

    /**
     * Dependency injection using a setter method
     */
    public function setBow(BowInterface $bow)
    {
        $this->bow = $bow;
    }

    public function shoot($target)
    {
        return $this->bow->shoot($target);
    }
}

Ahora la clase Elf recibe el arco como parámetro a través del constructor de la clase, es decir que cuando creemos un elfo podemos inyectar un arco diferente:

Código :

$elf = new Elf(new LongBow);

También podemos cambiar de arco en cualquier momento usando el método setter, otra forma de inyectar una dependencia:

Código :

$elf->setBow(new LongBow);

Uso de interfaces

Una interfaz nos permite crear implementaciones de forma segura. En nuestro ejemplo siempre que “LongBow” o cualquier arco que creemos “implemente” la interfaz "BowInterface" podrá ser usada por el objeto Elf sin problemas:

Código :

class LongBow implements BowInterface {
    public function shoot($target)
    {
        // A long bow should have more range and be more powerful
    }
}

[nota:502a2ffc0d]En una interfaz sólo definimos los “headers” de cada método que sea necesario implementar, ejemplo: public function shoot($target) las clases que implementen una interfaz deben definir cada uno de esos método con su correspondiente implementación de código.[/nota:502a2ffc0d]

Conclusión

La inyección de dependencias es el fondo un concepto sencillo que hará tus objetos mucho más flexibles y menos dependientes unos de otros.

En un próximo tutorial veremos este concepto con el framework Laravel ^^

Sígueme en Twitter si estás interesado en más tutoriales o quieres hacerme alguna consulta. :D

Enviar comentario

via Cristalab http://ift.tt/1mbfs7y

Advertisements

Tags:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: