Composite



Scaricare 0.68 Mb.
Pagina2/7
03.04.2019
Dimensione del file0.68 Mb.
1   2   3   4   5   6   7

2. Observer

Supponiamo di avere un insieme di dati e più Client che possono accedere ad esso.

I dati sono condivisi e devono restare consistenti nonostante possano essere modificati da alcuni Client (nel caso limite tutti i Client possono modificare i dati).

I Client che accedono all’insieme di dati in un dato istante possono non essere gli stessi Client che vi accedono in un tempo successivo.


Esempio:
I dati gestiti da un’Anagrafe vengono utilizzati per la gestione ordinaria, ma anche all’interno di fogli di calcolo, per eseguire statistiche, eccetera, cioè vengono condivisi da più Client.

In particolare gli stessi dati (che essendo numerosissimi sono memorizzati in un unico luogo senza ridondanze) possono essere rappresentati sul video in diversi modi: su Fogli Elettronici, su Istogrammi, su Diagrammi a Torta, eccetera.





Figura 11 - diag11.gif


Quando i dati vengono modificati sul Foglio Elettronico (che è una rappresentazione dei dati) occorre modificare anche l’insieme di dati dal quale il Foglio Elettronico attinge, in modo tale che Istogrammi e Diagrammi a Torta che accedono a tale insieme per essere tracciati, possano vedere i dati aggiornati e cioè vi sia sincronia tra i dati e le loro visualizzazioni.
Gli obiettivi che intendiamo perseguire sono:


  • rendere i dati condivisibili;

  • sincronizzare i dati e la loro visualizzazione;

  • indipendenza dall’implementazione;

  • rendere i Client insensibili al modo in cui i dati sono memorizzati.

I Client osservano i dati; per questo il pattern utilizzato prende il nome di Observer.

Esempio:
Supponiamo di avere un sistema che dispone di un orologio interno chiamato Real Time Clock (RT-Clock) aggiornato periodicamente da un Clock Esterno (External Clock).

Le applicazioni del sistema che fanno riferimento al RT-Clock sono il Pannello di Controllo (Control Panel) che gestisce l’orologio, l’applicazione che visualizza l’Orologio, lo Scheduler, un’Agenda Elettronica, eccetera.


F
igura 12 - diag12.gif

Il RT-Clock è la struttura dati condivisa che, in generale, nel pattern Observer viene chiamata Subject.


Un possibile pattern che persegue gli obiettivi che ci siamo posti è il seguente:
F
igura 13 - diag13.gif

All’interno dei Clock Clients (CK-Client) c’è una rappresentazione locale del tempo (TimeLocal). In generale, all’interno degli observer, c’è una rappresentazione locale dei dati contenuti nella classe Subject.

In ogni istante i dati contenuti nella subject e quelli locali degli observer devono essere consistenti, nel senso che deve esistere una sincronizzazione degli aggiornamenti. La gestione del problema della condivisione dei dati va ottenuta con un livello di astrazione superiore. Spieghiamo meglio con un esempio.

Supponiamo che uno degli observers abbia la facoltà di modificare i dati contenuti nella subject.

Per esempio il Pannello di Controllo ha la facoltà di modificare l’ora contenuta nell’RT-Clock (e cioè TimeRT) attraverso la SetTime(). Gli altri observer devono poter accorgersi in tempo reale dei cambiamenti avvenuti in modo tale da poter modificare immediatamente i propri dati locali rendendoli consistenti con quelli contenuti nella subject.

Non è pensabile di legare tra loro gli observers, per esempio creando dei collegamenti diretti tra il Pannello di Controllo e gli altri observers perché questa soluzione non è modulare e rende difficoltosa l’introduzione di eventuali nuovi observers.


Chiariamo quest’ultima affermazione con un esempio.

Supponiamo che, ad un tempo iniziale, il sistema sia costituito dal RT-Clock, dal Pannello di Controllo e dall’applicazione che visualizza l’Orologio. RT-Clock è la subject; il Pannello di Controllo e l’Orologio sono gli observers. Potremmo pensare di collegare direttamente il Pannello di Controllo e l’Orologio in modo tale da sincronizzare i dati nella subject e quelli degli observers.




(Disegno nuovo 1 ) diag13b.wmf


Come abbiamo già detto, questa soluzione non è modulare perché introduce il vincolo che Pannello di Controllo e Orologio debbano sempre e solo lavorare insieme, quindi anche solo una sconnessione (detach) dell’Orologio, ad esempio, comporta la riprogettazione del sistema.

Anche l’introduzione di nuovi observers comporta la necessità di riprogettare il sistema, con questa soluzione. Supponiamo, infatti, di introdurre (Attach) l’observer che gestisce l’I/O. Esso dovrà essere connesso sia alla subject che al Pannello di Controllo come nella figura seguente:




(Disegno nuovo 2 ) diag13c.wmf


Supponiamo poi di introdurre l’observer Scheduler. Esso è uno degli observer che può anche modificare i dati nella subject. Allora anche tra lo Scheduler e gli altri observers va effettuato un collegamento diretto. Lo Scheduler potrà a sua volta aggiornare il Pannello di Controllo:


(Disegno nuovo 3 ) diag13d.wmf


E’ già a questo punto evidente la complessità e la rigidità di questo modello non object-oriented.
Torniamo al diagramma in OMT o UML:

Quando un Client si aggiunge alla lista dei Viewers che stanno osservando il RT-Clock, chiama la Attach() del Clock-Handler; quando si toglie dalla lista, chiama la Detach().


Il pattern Observer ha un diagramma dinamico che può essere il seguente:

Figura 13 e - diag13e.gif


( NB: Il pattern Composite non ha un diagramma dinamico perché è un pattern strutturale e non ha dinamica. )
Sul diagramma dinamico viene rappresentata la sequenza delle operazioni nel tempo.

Su questo diagramma abbiamo rappresentato a sinistra l’andamento delle operazioni del Real Time Clock che è un’istanza della classe RT-Clock.

Ck1, Ck2, Ck3 sono tre possibili istanze della classe Ck-Client.

Sebbene la sequenza delle operazioni nel tempo sia la stessa, il contenuto e l’azione di tali operazioni cambia a seconda dell’implementazione usata. Per spiegare il diagramma dinamico dobbiamo allora distinguere tra due possibili modelli di observer, che differiscono tra loro nel funzionamento:



Push model




Figura 14 - diag14.gif


Per spiegare il funzionamento di questo modello consideriamo quest’ultimo diagramma OMT, il diagramma dinamico e il diagramma OMT dell’esempio considerato precedentemente.
Uno dei ConcreteObserver appartenenti alla lista dei Viewers (nel diagramma dinamico Ck2) richiama la SetState() ( nell’esempio SetTime() ) della ConcreteSubject (RT-Clock). SetState() ha la funzione di modificare i dati nella ConcreteSubject, cioè il subjectState (TimeRT).

La ConcreteSubject lancia la Notify() che nel caso del push model ha la funzione di lanciare la Update() di ogni ConcreteObserver nella lista dei Viewers. Attraverso la Update() i dati locali contenuti nei ConcreteObserver, cioè l’observerState (TimeLocal) vengono aggiornati immediatamente indipendentemente dalla “volontà” del ConcreteObserver, attraverso la GetState() ( GetTime() ) che ha la funzione di restituire il subjectState.


Usando il push model la Subject cioè, in generale, la struttura dati condivisa, aggiorna sempre i dati locali degli Observers, anche quando gli Observers non necessitano realmente di conoscere nel dettaglio i cambiamenti avvenuti nella Subject.

Ciò presuppone che la Subject faccia delle assunzioni a priori sulle classi degli Observers, perciò il push model potrebbe rendere tali classi poco riusabili.

Inoltre quando la Subject cambia stato tutti gli Observer sono costretti a perdere tempo per aggiornare i propri dati locali anche quando in realtà non ne avrebbero bisogno perché non stanno usando i dati della Subject. Questo fenomeno di perdita di tempo viene accentuato se lo stato della Subject viene aggiornato frequentemente.

Però, automatizzando gli aggiornamenti dei dati locali, questo modello evita l’inconsistenza dei dati.


Per spiegare meglio questi concetti, vediamo un esempio.

Supponiamo di avere un sistema formato dalla subject RT-Clock e dagli observers Pannello di Controllo, visualizzatore dell’Orologio, Scheduler, modulo di I/O. Supponiamo inoltre che tra gli observers vi sia anche un’applicazione che permetta di lavorare su Fogli Elettronici. Tale applicazione consente, una volta terminato l’editing, di stampare il foglio elettronico su carta corredando la stampa automaticamente della Data e Ora di stampa.

Supponiamo che il sistema lavori utilizzando l’ora solare.

Ad un certo istante il Clock Esterno segnala alla subject RT-Clock che è stata introdotta l’ora legale e TimeRT viene modificato.

Utilizzando il push model, la subject assume che tutti i suoi observers desiderino sempre essere aggiornati non solo del fatto che è avvenuto un cambiamento nei dati della subject, ma vogliano che i propri dati locali vengano immediatamente aggiornati.

Questa condizione rende gli observers poco riusabili nel senso che, essendo state fatte su di essi delle assunzioni a priori da parte della subject, il loro utilizzo è limitato a sistemi in cui si tiene conto di tali assunzioni.

L’aggiornamento dei dati locali negli observers richiede tempo. Con il push model ogni volta che lo stato della subject cambia, viene impiegato comunque tempo per aggiornare i dati locali degli observers. A volte, però, tale aggiornamento può essere inutile, come nel caso dell’applicazione che lavora con i Fogli Elettronici, la quale ha realmente necessità di conoscere l’ora nel dettaglio solo al momento della stampa.

A questo punto potrebbe essere fatta l’obiezione che ogni observer considerato ha un suo orologio locale funzionante (TimeLocal) e l’ora viene cambiata da solare a legale e viceversa due sole volte all’anno.

Un esempio più significativo concerne una subject contenente dati che vengono continuamente aggiornati da vari observers, come nel caso dei dati osservati da un Foglio Elettronico e da un’applicazione per tracciare Diagrammi a Torta. L’utente che utilizza il Foglio Elettronico cambia molto frequentemente i dati sul foglio e nella subject. Ma l’applicazione che permette di tracciare i Diagrammi a Torta che si basano sui dati della subject necessita realmente di conoscere quali cambiamenti sono avvenuti (e quindi di modificare i propri dati locali) solo quando viene richiesto di tracciare un Diagramma a Torta.

Il problema, nel caso in cui non si utilizzi il push model, è che gli observers devono “ricordarsi” di controllare se sono avvenuti dei cambiamenti nella subject ed eventualmente modificare i propri dati locali prima di usarli, tutte le volte che vogliono usarli. Questo implica che la gestione del controllo va lasciata:



  • o all’observer (applicazione che traccia Diagrammi a Torta), ma ciò comporta delle pre-assunzioni sulla sua classe e quindi poca riusabilità;

  • o all’utente (che si occupa personalmente di aggiornare i dati locali dell’applicazione che traccia i Diagrami a Torta ogni volta che vuole tracciarne uno), ma l’utente è “umano” e potrebbe dimenticare di aggiornare i dati locali prima di usarli, portando all’inconsistenza dei dati. Il push model, invece, come abbiamo già detto, automatizza gli aggiornamenti evitando l’inconsistenza dei dati.






Condividi con i tuoi amici:
1   2   3   4   5   6   7


©astratto.info 2017
invia messaggio

    Pagina principale