En este screencast voy a explicaros el patrón de diseño Observer (observador) en PHP, que consiste en crear objetos observables que mantienen una lista de observadores y les notifica a éstos de cualquier cambio en su estado, normalmente llamando a uno de sus métodos. Este patrón suele utilizarse para implementar un sistema de manejo de eventos distribuido, por ejemplo construir un sistema de logging en el que registramos el observador (clase que se ocupa de escribir el log) en cada objeto que queramos que envíe mensajes al log.
Ver screencast (duración: 12:09)
- Descargar videotutorial en alta calidad – MOV (22 MB)
- Descargar videotutorial optimizado para iPod/iPhone – M4V (16 MB)
Podéis ver el resto de screencasts en la página de videotutoriales, o suscribiros al podcast de iTunes. Os recomiendo especialmente que no os perdáis los tutoriales de dos de los patrones más usados: el Singleton y el Factory Pattern.
Ejemplo de implementación
En primer lugar creamos la clase abstracta de la que heredarán las clases observables, y el interfaz que implementarán los observadores.
<?php abstract class Observable{ protected $observers; function __construct(){ $this->observers = array(); } public function registrarObserver($observer){ if(!in_array($observer, $this->observers)){ $this->observers[] = $observer; } } public function deregistrarObserver($observer){ if(in_array($observer, $this->observers)){ $key = array_search($observer, $this->observers); unset($this->observers[$key]); } } abstract public function notificarObservers(); } interface Observer{ public function notificar($sender, $params); } ?> |
A continuación creamos las clases específicas, en este caso una clase observable y dos clases de logging que actuarán de observadores.
<?php class MiObservable extends Observable{ public function __construct(){ parent::__construct(); } public function notificarObservers(){ foreach ($this->observers as $observer) { $observer->notificar($this, $this->param); } } public function Evento($texto){ $this->param = $texto; $this->notificarObservers(); } } class Log implements Observer{ public function notificar($sender, $param){ echo get_class($sender)." envio $param a las ".date('h:i:s', time())."<br />"; } } class SalvarLog implements Observer{ public function notificar($sender, $param){ echo "Guardando en BD $param enviado por ".get_class($sender)."... <br /><br />"; } } ?> |
Para utilizarlo, instanciaremos las clases y registraremos los observadores de esta manera:
<?php $obj = new MiObservable(); $obj->registrarObserver(new Log()); $obj->registrarObserver(new SalvarLog()); $obj->Evento('Test 1'); sleep(1); $obj->Evento('Test 2'); $obj->deregistrarObserver(new SalvarLog()); $obj->Evento('Test 3'); ?> |
Muy bueno
sigue asi amigo
Hola David,
Muy bien explicado el patrón. Además es un patrón muy útil. Sigue así que los estas haciendo fenomenal y si conoces algún patrón más estaría muy bien incluirlo en tus futuros videotutoriales.
¿Podrías dar un ejemplo de caso práctico de uso de este patrón que no sea el de logging? Muchas gracias por el vídeo tutorial, muy bueno.
@Agustin Pues por ejemplo un motor de blog, en el que creas una clase Post observable y un par de clases Feed y Mail que implementen observer. De esa manera cuando añadas un post nuevo, la clase Post notifica a las clases Feed y Mail que se ha creado un post nuevo, para que cada una actualice el feed y envíe un mail a los suscritos vía email, respectivamente.
Muy bueno, gracias, y estoy bajando los demas tutos.
Excelente!!! gracias por el aporte! ahora tengo una herramienta más con la cual contar al momento de armar algo!! gracias!
Excelente explicación. Constituye un material excelente para la docencia.
Muchas gracias
Ok! Muy bueno el ejemplo! Muchas gracias por el aporte!
Muy buen tutorial :), me ha sido de gran ayuda, sólo hay algo que me ha confundido un poco y es que el Observer tenga una funcion llamada notificar, cuando realmente el Observer no notifica sino que procesa la notificación. Sería más correcto llamar esta función procesarNotificacion.
Qué opinas?