PHP Avanzado: Patrones de diseño

Post on 12-Jun-2015

19.666 views 1 download

description

¿Qué son los patrones de diseño?. El patrón Singleton. El patrón RegistryEl patrón Factory. El patrón DecoratorEl patrón Observer. El patrón Front Controller. El patrón MVC

Transcript of PHP Avanzado: Patrones de diseño

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.1. ¿Qué son los patrones de diseño?

Bloque II: Patrones de diseño

Son soluciones a problemas cotidianos, son independientes de la tecnología utilizada y permiten crear un argot común.

Desarrollo web avanzado con PHP 5

2.1. ¿Qué son los patrones de diseño?

Bloque II: Patrones de diseño

Un poco de historia:

● En 1977 Christopher Alexander aplica en concepto de patrón (“pattern”) a la arquitectura.

● En 1987 Kent Beck y Ward Cunningham se plantean aplicar este concepto de patrón al sofware

● En 1994 se publica “Design Patterns: Elements of Reusable Object-Oriented Software” por la Gang Of Four (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides)

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.2. El patrón Singleton

Bloque II: Patrones de diseño

Problema

Tener acceso a un recurso único que nunca sea duplicado y que además esté disponible en cualquier parte de la aplicación, sin tener que preocuparse de su existencia.

Desarrollo web avanzado con PHP 5

2.2. El patrón Singleton

Bloque II: Patrones de diseño

Ejemplo

Necesitar instanciar un objeto que nos de acceso a la base de datos, pero que nos devuelva siempre la misma conexión.

Desarrollo web avanzado con PHP 5

2.2. El patrón Singleton

Bloque II: Patrones de diseño

Implementación

class DB{

  private static $singleton;  private $connection;  private function __construct(){

$this­>conection = mysql_connect();

}

  public static function getInstance(){    if(is_null(self::$singleton){      self::$singleton = new DB();    }    return self::$singleton;  }}

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.3. El patrón Registry

Bloque II: Patrones de diseño

Problema

Permitir que cualquier objeto sea usado como un Singleton sin necesidad de especificarlo directamente en su constructor

Desarrollo web avanzado con PHP 5

2.3. El patrón Registry

Bloque II: Patrones de diseño

Ejemplo

Crear un objeto que sea una base de datos que se pueda recuperar como si fuera un singleton.

Desarrollo web avanzado con PHP 5

2.3. El patrón Registry

Bloque II: Patrones de diseño

Implementacion

class Registry{

  private static $register;

  public static function add($item){     if(is_object($item)){

$name = get_class($item);

    }else{throw new Exception('Objeto incorrecto');

    }    self::$register[$name] = $item;  }

Desarrollo web avanzado con PHP 5

2.3. El patrón Registry

Bloque II: Patrones de diseño

Implementación (continuación)

  public static function get($name){if(array_key_exists($name, self::$register)){

      return self::$register[$name];    }else{

throw new Exception('Clase no registrada');

    }  }}

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.4. El patrón Factory

Bloque II: Patrones de diseño

Problema

Necesitamos instanciar una o más clases especializadas que se encargan de hacer la misma tarea.

Desarrollo web avanzado con PHP 5

2.4. El patrón Factory

Bloque II: Patrones de diseño

Ejemplo

Necesitamos cargar los parámetros de configuración de nuestra aplicación, pero estos podrán provenir de un XML o un archivo en PHP.

Desarrollo web avanzado con PHP 5

2.4. El patrón Factory

Bloque II: Patrones de diseño

Solución

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Problema

Permitir herencia múltiple evitando que el árbol de clases crezca de manera desmesurada.

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Estamos programando un juego de estrategia y creamos una clase “Tile” (tesela) para el mapa. Cada tesela permite una velocidad.

abstract class Tile{

  abstract function getSpeed();}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Para crear una “Montaña” (Mountain) bastará con esto

class Mountain extends Tile{  private $speed = 10;

  function getSpeed(){return $this­>speed;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Y si queremos que la montaña esté congelada

class FrozenMountain extends Mountain{

  function getSpeed(){return parent::getSpeed() + 2;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Y si ahora queremos que la montaña esté embarrada

class MuddyMountain extends class Mountain{

  function getMoveRate(){return parent::getSpeed() ­ 2;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Y si necesitamos una montaña embarrada y congelada

Y si ahora también tenemos explanadas

Y si también pueden estar atravesadas por ríos

...

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Ejemplo

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

El secreto para resolver correctamente este problema se basa en delegar responsibilidades.

Seguimos manteniendo las primeras clases del árbol

class Mountain extends class Tile{  private $speed = 10;

  function getMoveRate(){return $this­>speed;

  }} abstract class Tile{

  abstract function getSpeed();}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Creamos una nueva clase encargada de “decorar”

abstract class TileDecorator extends Tile{

  protected $tile;

  function __construct(Tile $tile){$this­>tile = $tile;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Redefinimos nuestras clases “Congelada” y “Embarrada”

class MuddyDecorator extends TileDecorator{

  function getSpeed(){return $this­>tile­>getSpeed()­2;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Redefinimos nuestras clases “Congelada” y “Embarrada”

class FrozenDecorator extends TileDecorator{

  function getSpeed(){return $this­>tile­>getSpeed()+2;

  }}

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Creando una Montaña Congelada

$tile = new FrozenDecorator(              new Mountain()        );

return $title­>getSpeed() // 12

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Creando una explanada congelada y embarrada

$tile = new MuddyDecorator(              new FrozenDecorator(                    new Plain()              )        );

return $title­>getSpeed() // 10

Desarrollo web avanzado con PHP 5

2.5. El patrón Decorator

Bloque II: Patrones de diseño

Implementación

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Problema

Una clase adquiere responsabilidades que no le son específicas como consecuencia de un evento que sucede en su interior

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

Consideremos una clase responsable del acceso de usuarios al sistema

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemploclass Login{  const LOGIN_GRANTED = 1;  const LOGIN_DENIED  = 2;  private $status = array();  public function handleLogin($user, $pass, $ip){

switch(rand(1,2)){case 1:

   $this­>setStatus(self::LOGIN_GRANTED, $user, $ip);$ret = true;break;

case 2:    $this­>setStatus(self::LOGIN_DENIED, $user, $ip);

$ret = false;break;

    }     return $ret;  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

La clase Login tendría además su correspondiente getter y setter del atributo status

class Login{

  // … codigo anterior

  public function getStatus(){return $this­>status;

  }

  public function setStatus($status, $user, $ip){$this­>status = array($status, $user, $ip);

  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

A las dos semanas de empezar a desarrollar el proyecto nos hacen una ampliación de los requisitos

Necesitamos que cada vez que un usuario intente acceder al sistema se registre su ip de acceso

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

class Login{

  // … codigo

  public function handleLogin($user, $pass, $ip){switch(rand(1,2)){

// … código    }

    Logger::logIP($user, $ip, $this­>getStatus());

    return $ret;  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

Un mes después, la ampliación de requisitos continúa

En caso de un intento de login fallido necesitamos que el sistema envíe un email de notificación

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

class Login{  // … codigo  public function handleLogin($user, $pass, $ip){    switch(rand(1,2)){

// … código    }

    Logger::logIP($user, $ip, $this­>getStatus());

    if(!$ret){     Notifier::mailWarning($user, $ip, $this­>getStatus());    }

    return $ret;  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Ejemplo

Tras quince días de calma, vuelven a solicitar nuevos cambios

Necesitamos añadir una cookie a aquellos usurios que sí que consigan acceder al sistema.

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

Desenganchamos los elementos clientes (observadores) de la clase central (observable o sujeto).

Los observadores son notificados por el sujeto de qué evento tiene lugar

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

La interfaz “IObservable”

interface IObservable {

  function attach(Observer $observer);

  function detach(Observer $observer);

  function notify();

}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

class Observable implements IObservable {  private $observers;

  function attach(Observer $observer){    $this­>observers[] = $observer;  };

  function detach(Observer $observer){    $key = array_search($this­>observers, $observer);    unset($this­>observers[$key]);  };

  function notify(){    foreach($this­>observers as $observer){      $observer­>update($this);    }  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

La interfaz “IObserver”

interface IObserver {

  function update(Observable $observable);

}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

class Login extends Observable{  // … codigo  public function handleLogin($user, $pass, $ip){    switch(rand(1,2)){

// … código    }

    $this­>notify();

    return $ret;  }}

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

A las dos semanas de empezar a desarrollar el proyecto nos hacen una ampliación de los requisitos

Necesitamos que cada vez que un usuario intente acceder al sistema se registre su ip de acceso

Desarrollo web avanzado con PHP 5

2.6. El patrón Observer

Bloque II: Patrones de diseño

Implementación

class Logger implements Observer {

  // otro código 

  function update(Observable $observable){    $this­>log($observable­>getStatus());  };

}

$login = new Login();$login­>attach(Logger::getInstance());

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.7. El patrón Front Controller

Bloque II: Patrones de diseño

Problema

Proporcionar un único punto de entrada para todas las peticiones

Desarrollo web avanzado con PHP 5

2.7. El patrón Front Controller

Bloque II: Patrones de diseño

Solución

Todas las peticiones deben ser procesadas por un único script, por ejemplo index.php

Desarrollo web avanzado con PHP 5

2.7. El patrón Front Controller

Bloque II: Patrones de diseño

Ejemplo

Tenemos una web muy simple formada por tres pantalla: Inicio, Servicios y Contacto.

Desarrollo web avanzado con PHP 5

2.7. El patrón Front Controller

Bloque II: Patrones de diseño

Solución

// index.php$page = isset($_GET['page'])?_GET['page']:'inicio'; 

include('pages/'.$page.'.php'); 

Desarrollo web avanzado con PHP 5

2.7. El patrón Front Controller

Bloque II: Patrones de diseño

URL Amigables

http://www.midominio.com/producto.php?id=1

vs

http://www.midominio.com/producto/mac-book-pro-13

nos conformaremos con

http://www.midominio.com/index.php?/producto/mac-book-pro-13

Desarrollo web avanzado con PHP5

Bloque II: Patrones de diseño

1. ¿Qué son los patrones de diseño?

2. El patrón Singleton

3. El patrón Registry

4. El patrón Factory

5. El patrón Decorator

6. El patrón Observer

7. El patrón Front Controller

8. El patrón MVC

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

El patrón MVC para una aplicación web

ModeloRepresenta la información sobre la que opera la aplicación

VistaMuestra la información del modelo, normalmente HTML

ControladorResponde a las peticiones del usuario y actuando de “pegamento” entre modelo y vista

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Un ejemplo, listando los artículos de un blog

<?php

// Conectando con la base de datos

try{$dbh = new PDO(

             'mysql:host=server.flai.es;dbname=curso_php_blog',             'curso',             'curso_2010');

echo "Conexion correcta";

}catch (Exception $e){echo "Error: ".$e­>getMessage();die();

}

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Un ejemplo, listando los artículos de un blog

// Ejecutando la SQL

$stm = $dbh­>prepare(  'SELECT title, created_at    FROM article    ORDER BY created_at    DESC LIMIT 10');

$stm­>execute();

$results = $stm­>fetchAll();

?>

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Un ejemplo, listando los artículos de un blog

<html>   <head>     <title>Listado de articulos</title>   </head>   <body>    <h1>Listado de articulos</h1>    <table>      <tr><th>Date</th><th>Title</th></tr> <?php foreach($results as $result) { echo "\t<tr>\n"; printf("\t\t<td> %s </td>\n", $result['created_at']); printf("\t\t<td> %s </td>\n", $result['title']); echo "\t</tr>\n"; } ?>     </table>   </body> </html>

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Mejorando el código

try{$dbh = new PDO('dsn';

}catch (Exception $e){   die("Error: ".$e­>getMessage();}

$stm = $dbh­>prepare('SELECT * FROM article LIMIT 10');$stm­>execute();$articles = $stm­>fetchAll();

unset($dbh);

require('view.php');

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Mejorando el código (archivo view.php)

<html>  <head>    <title>Listado de artículos</title>  </head>  <body>    <h1>Listado de artículos</h1>    <table>      <tr><th>Fecha</th><th>Titulo</th></tr>    <?php foreach ($articles as $article): ?>      <tr>        <td><?php echo $article['created_at'] ?></td>        <td><?php echo $article['title'] ?></td>      </tr>    <?php endforeach; ?>    </table>  </body></html>

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Mejorando el código aún más (index.php)

<?php

require('model.php');

$articles = getAllArticles();

require('view.php');

?>

Desarrollo web avanzado con PHP 5

2.8. El patrón MVC

Bloque II: Patrones de diseño

Mejorando el código aún más (model.php)

function connect($dsn){  try{    $dbh = new PDO($dsn);  }catch (Exception $e){    die("Error: ".$e­>getMessage());  }  return $dbh;}

function getAllArticles(){  $dbh = connect($dsn);  $stm = $dbh­>prepare('SELECT * FROM article');  $stm­>execute();  $articles = $stm­>fetchAll();  unset($dbh);  return $articles;}