Design Pattern Observer INGEGNERIA DEL SOFTWARE Nicola Ferrari Carta d’identità Nome Alias Dependents Publish-Subscribe Classificazione Observer Comportamentale, basato su oggetti Scopo Definisce una relazione uno a molti tra oggetti, in modo tale che quando un oggetto cambia stato tutti gli oggetti da lui dipendenti vengono automaticamente notificati 2 Motivazioni Un esempio noto a tutti Il foglio elettronico e le sue opportunità. I dati in forma tabellare possono essere rappresentati nei diversi tipi di grafici. Observer si preoccupa della sincronizzazione automatica fra tutte queste parti. Cioè l’aggiornamento dei valori di certe celle provoca il ridisegno dei grafici. 3 Applicabilità Quando un’astrazione presenta due aspetti, di cui uno dipende dall’altro. Quando una modifica ad un oggetto richiede modifiche ad altri oggetti che dipendono da questo. Quando si vuole mantenere un alto livello di disaccoppiamento fra gli oggetti. 4 I partecipanti Gli attori (visione globale) Subject (abstract) Observer (interface) ConcreteSubject ConcreteObserver 5 I partecipanti Subject Classe astratta da cui eredita ConcreteSubject Tiene i riferimenti ai vari observers metodi add e remove attributo observers Informa gli observers di un avvenuto cambiamento di stato metodo notify 6 I partecipanti Subject (il codice) notify() delega ad Observer l’aggiornamento dello stato Mancano le astrazioni di setState e getState public abstract Subject { protected int state; protected ArrayList observers; public void add(Observer o) { observers.add(o); } public void remove(Observer o) { int i = observers.indexOf(o); if (i>=0) observers.remove(o); } public void notify() { for (int i=0; i<=observers.size();i++) { Observer o = (Observer) observers.get(i); o.update(); } } …. } 7 I partecipanti Observer interfaccia implementata da ConcreteObserver ConcreteObserver Tiene riferimento a Subject per leggere lo stato 8 Implementazione ConcreteObserver (il codice) public class ConcreteObserver implements Observer { private String id; private int state; private Subject subject; public ConcreteObserver(String Id, Subject subject) { this.id = Id; this.subject = subject; stato = id.length(); update richiede lo stato } tramite getState dal soggetto public void update() { concreto state = state+subject.getState(); } } 9 Ricapitolando Il metodo notify chiama il metodo update da tutti gli Observer registrati. Il metodo update a sua volta richiama getState di ConcreteSubject per ottenere il nuovo stato 10 Conseguenze 1. Accoppiamento astratto fra Subject e Observer 2. Supporto broadcast 3. Aggiornamenti inattesi per comunicazioni 11 Implementazione Mantenere le associazioni fra soggetti ed osservatori 1. Usando una tabella di hash Un soggetto senza osservatori non occupa spazio Sarà più oneroso accedere agli osservatori 12 Implementazione Chi fa partire la notifica? 2. I metodi di Subject quando modificano il proprio stato automaticamente chiamano Notify dopo aver cambiato lo stato del soggetto Inefficienza nel caso di aggiornamenti multipli I client devono invocare Notify sull’oggetto al momento opportuno. Si corre il rischio di dimenticarsene. 13 Implementazione Riferimenti a soggetti cancellati 3. La cancellazione di un soggetto non dovrebbe produrre riferimenti non validi negli osservatori Il soggetto notifica ai suoi osservatori la propria cancellazione in modo che questi possano eliminare il riferimento al soggetto 14 Implementazione Evitare protocolli di notifica specifici per l’osservatore 4. Le implementazioni prevedono che il soggetto alleghi nella notifica informazioni addizionali sul cambiamento avvenuto nell’osservatore Modello push: si allegano informazione dettagliate Problema di riusabilità. Modello pull: non si allega nulla Gli Observer devono capire cosa è cambiato 15 Implementazione Incapsulare semantiche complesse di aggiornamento 5. Quando la dipendenza fra soggetti e osservatori è particolarmente complessa, potrebbe essere richiesto un oggetto che mantenga queste associazioni Maggior sincronizzazione fra osservatori e soggetto 16 Utilizzi noti Gestione degli eventi degli widget di una GUI Gestione degli eventi di un alarm clock Model View Control 17 Pattern correlati Mediator svolge il ruolo di mediatore fra soggetto e osservatori Vedi lucido 16 Singleton 18