Patrones de diseño en PHP
Creo que todo programador PHP debe tener claro algunos patrones muy usados en los proyectos web, a modo de recursos me gustaría que los tuvieseis a mano.
He simplificado el código al máximo saltándome en algunas ocasiones las interfaces, pero hay que usarlas.
De los UML ni os cuento, pero debería haberlos puesto también.
Tenéis mucha mas información en la wikipedia:
http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o
Existe tres tipos de patrones:
- Creacionales
- Estructurales
- Comportamiento
Creacionales
Factoría
La particularidad que tienen este patrón es que un método proporciona clases.
Por ejemplo supongamos que tenemos una tienda en la que se venden productos, pero el precio de estos productos no es de tipo estático sino que requiere de una función propia del producto.
[sourcecode language="php"]
getPrice();
$productoB = carrito::getProduct('B');
echo $productoB->getPrice();
?>
[/sourcecode]
Singleton
El patrón singletone se usa para obtener un recurso y que este este una y sólo una vez creado, obteniéndose instancias de este.
Es muy util este patrón para conexiones con la base de datos.
[sourcecode language="php"]
[/sourcecode]
Estructurales
Fachada
Basándonos en ejemplo de la factoría donde devolvíamos un producto, supongamos que tenemos una tienda y el precio del producto no es estático, sino que cada producto calcula su precio (pj depende de la oferta y la demanda y tiene que hacer una petición al mercado de valores), la tienda es una fachada que a pesar de tener la función getPrice($type), le pasa la pelota de calcular el precio al producto en cuestión ya que no sabe que tiene que hacer para calcular el precio.
[sourcecode language="php"]
productA = new ProductA();
$this->productB = new ProductB();
}
function getPrice($type) {
if ($type == "A")
return $this->productA->getPrice();
if ($type == "B")
return $this->productB->getPrice();
}
}
class ProductA implements IProduct {
function getPrice() {
return 3;
}
}
class ProductB implements IProduct {
function getPrice() {
return 4;
}
}
$tienda = new tienda();
echo $tienda->getPrice("A");
echo $tienda->getPrice("B");
?>
[/sourcecode]
Comportamiento
Observador
Este patrón pretende informar a todos los elementos, por ejemplo supongamos un juego donde hay jugadores que tienen 2 métodos, informar y ser informados, el observador informa a todos los jugadores, cuando sucede un evento.
[sourcecode language="php"]
jugadores[$jugador->id] = $jugador;
}
function evento($jugador, $info) {
foreach ($this->jugadores as $jugadork) {
if ($jugador != $jugadork) {
$jugadork->evento($this, $info);
}
}
}
function turno($id) {
$jugador = $this->jugadores[$id];
$this->evento($jugador, "informar");
}
}
class jugador {
public $id;
function __construct() {
$this->id = rand(1, 10);
}
function evento($juego, $info) {
if ($info == "mensaje") {
echo $this->id . ": me he llegado un mensaje";
}
if ($info == "informar") {
echo $this->id . ": envia un mensaje";
$juego->evento($this, "mensaje");
}
}
}
$juego = new Juego();
$jugador1 = new jugador();
$jugador2 = new jugador();
$juego->addJugador($jugador1);
$juego->addJugador($jugador2);
echo $jugador1->id . " y " . $jugador2->id . " en la partida";
$juego->turno($jugador1->id);
?>
[/sourcecode]
Cadena de mando
La cadena de mando o Chain of Responsibility, consiste en ejecutar un determinado comando pero en un orden de prioridades.
Supongamos que tenemos un array que contiene objetos que implementan cierta interfaz y que están ordenados por su prioridad.
Para ilustrarlo usaremos las tres leyes de la robótica.
[sourcecode language="php"]
leyes = array();
}
function addLey($ley) {
$this->leyes[] = $ley;
}
function executa($accion) {
foreach ($this->leyes as $ley) {
$ley->cumpleLey($accion);
}
}
}
class Ley implements ILey {
private $mensaje;
function __construct($mensaje) {
$this->mensaje = $mensaje;
}
function cumpleLey($accion) {
if ($accion) {
echo $this->mensaje;
}
}
}
$robot = new Robot();
$ley1 = new Ley("Un robot no puede hacer daño a un ser humano o, por inacción, permitir que un ser humano sufra daño.");
$ley2 = new Ley("Un robot debe obedecer las órdenes dadas por los seres humanos, excepto si estas órdenes entrasen en conflicto con la Primera Ley.");
$ley3 = new Ley("Un robot debe proteger su propia existencia en la medida en que esta protección no entre en conflicto con la Primera o la Segunda Ley.");
$robot->addLey($ley1);
$robot->addLey($ley2);
$robot->addLey($ley3);
$robot->executa("Haz el tonto");
?>
[/sourcecode]
Aunque en este sencillo ejemplo ejecutaría cualquier acción, lo que quería mostrar es que se ejecutan las leyes en un orden como en una cadena de mando.
Felicitaciones……Excelente tutorial, yo conocia algo de patrones de diseño, pero ya con este aporte uno se saca de muschas dudas.
Gracias totales..