El patrón observer

Hoy me ha tocado hablar en una charla en PHPVigo sobre el patrón Observer.
Por aquí dejo la presentación (Observer a partir de la página 66) y un pequeño resumen.

Qué hace

Permite a un objeto mantener una lista de objetos a los que notifica cuando su estado cambia.

Conceptos que se manejan

  • SUBJECT (aka OBSERVABLE) El objeto que notifica su cambio de estado a los que lo observan.
  • OBSERVER Lista de objetos que mantiene el objeto observable y que son notificados por él.

Interfaces

La interfaz para el objeto Observable es:

1
2
3
4
5
interface Observable {
public function attach (Observer $observer);
public function detach (Observer $observer);
public function notify();
}

y para el objeto observer:

1
2
3
interface Observer {
public function update (Observable $observable);
}

El patrón observer en la SPL (Standard PHP Library)

La librería estándar de PHP dispone de una serie de interfaces para implementar este patrón y una clase (SplObjectStorage) que permite al Observable almacenar los Observers a los que tiene que notificar.

SplObjectStorage dispone de los métodos attach y detach para añadir objectos o eliminarlos.

Ejemplo de implementación

ExampleSubject (Observable)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class ExampleSubject implements \SplSubject
{
private $storage;

public function __construct()
{
$this->storage = new \SplObjectStorage();
}

public function attach(\SplObserver $observer)
{
$this->storage->attach($observer);
}

public function dettach(\SplObserver $observer)
{
$this->storage->dettach($observer);
}

public function notify()
{
foreach ($this->storage as $observer) {
$observer->update($this);
}
}
}

En la línea 7 inicializamos un SplObjectStorage donde poder almacenar los Observers y
en la línea 23 vemos que de forma opcional podemos pasar el propio Observer a los observables como parámetro.

ExampleObserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ExampleObserver implements \SplObserver
{
public function __construct(\SplSubject $subject)
{
$subject->attach($this);
}

public function update(\SplSubject $subject)
{
if ($subject instanceof ExampleSubject) {
$this->doUpdate($subject);
}
}

public function doUpdate(ExampleSubject $subject) {
// Something to do
}
}

Ejemplo de utilización

Podéis ver un ejemplo muy sencillo en Github.

Compartir Comentarios