El patrón observador en PHP

El patrón de observación es bastante popular. Permite un tipo de comportamiento de suscripción a eventos. Diferenciamos el tipo de objeto de sujeto y observador (es). El observador es un objeto suscrito al cambio de estado del objeto sujeto. Cuando el sujeto cambia su estado, notifica automáticamente a todos sus observadores.

El siguiente ejemplo demuestra una posible implementación del patrón de observador:

<?php
class CheckoutSuccess implements \SplSubject
{
protected $salesOrder;
protected $observers;
public function __construct($salesOrder)
{
$this->salesOrder = $salesOrder;
$this->observers = new \SplObjectStorage();
}
public function attach(\SplObserver $observer)
{
$this->observers->attach($observer);
}
public function detach(\SplObserver $observer)
{
$this->observers->detach($observer);
}
public function notify()
{
foreach ($this->observers as $observer) {
$observer->update($this);
}
}
public function getSalesOrder()
{
return $this->salesOrder;
}
}
class SalesOrder
{
}
class Mailer implements \SplObserver
{
public function update(\SplSubject $subject)
{
echo 'Mailing ', get_class($subject->getSalesOrder()), PHP_EOL;
}
}
class Logger implements \SplObserver
{
public function update(\SplSubject $subject)
{
echo 'Logging ', get_class($subject->getSalesOrder()), PHP_EOL;
}
}
$salesOrder = new SalesOrder();
$checkoutSuccess = new CheckoutSuccess($salesOrder);
// some code…
$checkoutSuccess->attach(new Mailer());
// some code…
$checkoutSuccess->attach(new Logger());
// some code…
$checkoutSuccess->notify();

Las interfaces PHP\SplSubject y \SplObserver permiten una implementación de patrón de observador. Nuestro ejemplo de éxito de pago utiliza estas interfaces para implementar CheckoutSuccess como una clase para el tipo de objeto sujeto, y Mailer y Logger como clases para el tipo de objeto observador. Usando el método attach() de una instancia de CheckoutSuccess, adjuntamos ambos observadores al sujeto. Una vez que se llama al método notify() del sujeto, se activan los métodos update() del observador individual. Las llamadas al método getSalesOrder() pueden ser una sorpresa, ya que no existe un método getSalesOrder() real en instancias directas del objeto SplSubject. Sin embargo, las dos llamadas al método de actualización (\SplSubject $subject) en nuestro ejemplo recibirán una instancia de CheckoutSuccess. De lo contrario, la conversión de tipo del argumento $subject directamente a CheckoutSuccess nos daría un error fatal de PHP de la siguiente manera.

PHP Fatal error: Declaration of Logger::update(CheckoutSuccess $subject)
must be compatible with SplObserver::update(SplSubject $SplSubject)

Comparte