Il pattern observer (conosciuto anche come Publish-Subscribe Pattern) viene utilizzato per notificare ad uno o più oggetti il cambiamento di stato di un’altro oggetto, affinchè questi si aggiornino.
Il pattern, che si compone da un oggetto (Subject) e dai suoi osservatori (Observers), è un pattern comportamentale che definisce una relazione uno-a-molti tra gli oggetti in modo tale che, quando un oggetto cambia il suo stato, tutti gli oggetti dipendenti vengono notificati e aggiornati automaticamente.
Gli Observers saranno avvisati (notificati) ogniqualvolta lo stato del Subject cambia e potranno agire di conseguenza. Il Subject può avere qualsiasi numero di osservatori, ed un numero qualsiasi di Observers potranno “abbonarsi” al Subject in modo da riceverne le notifiche.
Da PHP 5.1, sono disponibili due interfacce (SplSubject, e SplObserver) all’interno della Standard PHP Library (SPL) che possono essere implementate per utilizzare il pattern Observer nelle nostre applicazioni.
Implementazione
Per implementare l’interfaccia SPLSubject dobbiamo implemetare tre metodi:
attach()
– Aggiunge un observer all’oggetto, memorizzandone un’istanza all’interno.detach()
– Rimuove un observer esistente dall’oggetto.notify()
– Notifica un cambiamento di stato a tutti gli observers.
L’interfaccia SplObserver è molto più semplice da implementare, difatti abbiamo un solo metodo, chiamato update()
, che prende il chiamante SplSubject come unico parametro.
Esempio
<?php class MyObserver1 implements SplObserver { public function update(SplSubject $subject) { echo __CLASS__ . ' - ' . $subject->getName(); } } class MyObserver2 implements SplObserver { public function update(SplSubject $subject) { echo __CLASS__ . ' - ' . $subject->getName(); } } class MySubject implements SplSubject { private $_observers; private $_name; public function __construct($name) { $this->_observers = new SplObjectStorage(); $this->_name = $name; } 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 getName() { return $this->_name; } } $observer1 = new MyObserver1(); $observer2 = new MyObserver2(); $subject = new MySubject("test"); $subject->attach($observer1); $subject->attach($observer2); $subject->notify(); /* Output: MyObserver1 - test MyObserver2 - test */ $subject->detach($observer2); $subject->notify(); /* Output: MyObserver1 - test */ ?>
Riassumendo
Il pattern Observer è un modello di progettazione particolarmente indicato quando il cambiamento di un oggetto richiede di cambiarne altri, senza sapere a priori quanti oggetti devono essere modificati, oppure quando un oggetto ha bisogno di segnalare ad altri senza sapere chi sono o quanti ce ne sono.
Questo modello consente di raggiungere un più elevato livello di coerenza tra oggetti correlati e dipendenti senza sacrificare la riutilizzabilità del codice.