Design Pattern in Java: Observer

In questo articolo vedremo come usare nei nostri programmi la classe Observable e l’interfaccia Observer, del package java.util, che implementano in Java il pattern Observer.

L’utilizzo del pattern Observer permette di risolvere elegantemente problemi che altrimenti richiederebbe qualche passaggio in più.

La classe Observable è utilizzata per creare delle sottoclassi osservabili da altre parti del programma: quando un oggetto Observable cambia, i suoi osservatori vengono avvisati immediatamente in modo quasi automatico. Le classi che osservano devono implementare l’interfaccia Observer e definire l’unico metodo dell’interfaccia, update. Questo metodo viene chiamato automaticamente quando l’oggetto osservato cambia. La sua firma è la seguente:

Innanzitutto bisogna creare la classe osservata, sottoclasse di Observable, e una classe osservatrice che implementi l’interfaccia Observer. Successivamente, quando l’oggetto osservato cambia, questo segnala il fatto a tutti gli osservatori registrati chiamando setChanged (prima) e notifyObservers (dopo). La firma di questi metodi è la seguente:

setChanged indica che l’Observable è stato modificato, mentre notifyObservers lo segnala agli osservatori.

Attenzione! se si chiama notifyObservers prima di setChanged, gli osservatori non riceveranno alcuna notifica!!

Da notare che notifyObservers è presente in due versioni: una con argomento, l’altra senza. Se si chiama notifyObservers con un argomento, questo verrà passato ad update, altrimenti ad update sarà passato il valore null. Questo argomento, essendo un Object, può essere un qualsiasi oggetto ed è molto utile per condividere dati tra gli oggetti.

Per rendere tutto funzionante, occorre registrare l’osservatore sull’oggetto osservato, usando il metodo addObserver. La sua firma, insieme a quella degli altri metodi di Observable, è qui sotto:

Per chiarire un pò le idee, qui sotto ho preparato un semplice esempio:

Questo programma è formato da un oggetto Observable che avvia un conto alla rovescia a partire da un valore specificato. Ad ogni modifica del conteggio, viene notificato il cambiamento all’unico osservatore. L’osservatore si occupa di stampare a schermo il valore ricevuto. Tra una notifica e la successiva il thread viene stoppato per 0.2 secondi solo per esigenze di visualizzazione.

Non c’è limite al numero di osservatori registrabili su uno stesso oggetto. Quest’altro esempio è una versione modificata dell’esempio precedente, con l’aggiunta di un secondo osservatore:

Il primo osservatore si comporta esattamente come nel caso precedente. Il secondo osservatore invece attende che il conto alla rovescia arrivi a zero per stampare a schermo la parola “FINE”.

 

Conclusioni

Observable ed Observer non sono aspetti fondamentali del linguaggio ma in certe occasioni possono tornare particolarmente utili, specialmente in applicazioni multithread. Saper usare bene queste due classi ci permetterà di risolvere in maniera semplice e raffinata problemi che altrimenti richiederebbero un impegno maggiore (ed un codice più confuso 😛 ).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *