Composite



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

5. Proxy

Supponiamo di avere un oggetto i cui costi di creazione e inizializzazione siano elevati.

Non tutte le attività che coinvolgono l’oggetto hanno realmente bisogno di crearlo (e cioè di sostenere dei costi). Spesso è sufficiente far riferimento ad un sostituto dell’oggetto (che tenga il posto all’oggetto reale) durante tutte le attività che lo consentono, in modo tale che la creazione effettiva dell’oggetto (e cioè il sostenimento reale dei costi) avvenga solo quando è strettamente necessario.
Esempio:

Vogliamo realizzare un Editor di documenti che possa creare pagine che includano testo e oggetti grafici.

Le immagini sono computazionalmente più pesanti da gestire rispetto al testo.

In fase di editing del testo, sostenere il costo derivante dalla visualizzazione delle immagini, per esempio, può risultare inutile. In questa fase, infatti, è sufficiente visualizzare un rettangolo (box) delle dimensioni dell’immagine, oppure un’anteprima a bassa risoluzione dell’immagine e solo in fase di stampa far riferimento all’immagine completa.

Questo metodo di gestione prende il nome di creation on demand (nel senso che l’immagine viene creata solo quando è richiesto) ed il pattern che lo realizza è il Proxy.

In questo esempio, per avere la creation on demand, occorre considerare come si presenta l’immagine quando:

- viene gestita al 100 % (immagine completa);

- viene trattata come proxy (anteprima o box).



Figura 42 - diag42.gif


L’interfaccia astratta (e quindi non istanziabile) Graph è comune nei due casi.

  • GetExtent() ottiene le dimensioni (altezza, larghezza) dell’immagine.

  • GetSize() ottiene quanta memoria occorre per memorizzare l’immagine.

  • Display(Mode) si occupa della visualizzazione dell’immagine. Mode permette di scegliere la risoluzione dell’immagine, che può essere alta, media, bassa oppure box.

  • Load() carica l’immagine in memoria.

Il diagramma dinamico è il seguente. Abbiamo tre possibili scenari:


Nel primo, il Document Editor fa una richiesta di chiamata a Create(), con conseguente chiamata della GetSize() della classe ImageProxy.

Figura 43 a - diag43a.gif

Nel secondo, viene caricata l’immagine in memoria solo per il tempo dedicato alla stampa e si suppone che l’immagine non venga mantenuta in memoria una volta finita la stampa, ma venga rimossa e quindi debba essere ricreata ad ogni stampa successiva.

Figura 43 b - diag43b.gif


Nel terzo, supponiamo che l’immagine, una volta caricata, resti in memoria e quindi non sia necessario caricarla da file ogni volta che occorre usare l’immagine per una stampa. In questo scenario la Load() della classe Image viene richiamata una sola volta.



Figura 43 c - diag43c.gif


NB: il primo ed il secondo scenario rappresentano due possibili strategie di creation on demand.
Come risulta dal diagramma dinamico, le chiamate dal mondo esterno sono sempre fatte al Proxy il quale funge da filtro fra il mondo esterno e la Image. ImageProxy maschera al Client (nell’esempio Document Editor) l’onere di certe attività, nel senso che se il Client potesse accedere direttamente ad un’unica classe Image senza dover passare attraverso il Proxy, ogni operazione dovrebbe contenere una serie di if sulle possibili modalità di visualizzazione dell’immagine (Mode) ed il Client dovrebbe occuparsi personalmente sia della gestione dell’immagine, sia della gestione del sostituto dell’immagine.
Le classi ImageProxy e Image sono sottoclassi dell’unica classe astratta Graph. In tal modo c’è un’unica interfaccia comune alle due classi. Questo consente ad un proxy di gestire più risorse e permette ad una risorsa di essere condivisa da più proxy.
Elenchiamo di seguito alcune situazioni comuni in cui è applicabile il pattern Proxy:
Creation on demand

Utilizza un virtual proxy che crea oggetti costosi a richiesta.

Nell’esempio visto viene utilizzata come virtual proxy la classe ImageProxy.
Copy on write

Utilizza un protection proxy che controlla l’accesso all’oggetto originale .

Per spiegare il funzionamento del copy on write consideriamo ad esempio una applicazione che elabora tracce sonore:



Figura 44 - diag44.gif


A, B, C sono eventi sonori appartenenti alle tracce ( Aa , Ab , A1 , A2 , A3 , A4 , A5 ) che compongono il brano.

La memorizzazione degli eventi sonori e’ onerosa e richiede molto spazio. Lo scopo del pattern Proxy è quello di fare in modo che i costi di gestione vengano sostenuti solo se è strettamente necessario.

L’evento sonoro C compare più volte in punti diversi del brano.

Abbiamo due possibili scelte :




  1. allocare in memoria una copia di C ogni volta che esso compare;

  2. allocare in memoria soltanto la prima copia di C e puntare ad essa ogni volta che, successivamente, occorre far riferimento a tale evento sonoro.

Il secondo caso comporta una minore occupazione di memoria, ma ha due inconvenienti:




  • non è possibile modificare una sola istanza dell’evento sonoro C senza dover modificare anche tutte le altre. Un modo per risolvere questo problema è allocare in memoria una ulteriore copia di C e modificare solo quella. In questo ci viene in aiuto il Proxy che gestisce in maniera trasparente l'allocazione quando risulta necessaria;




  • nel caso in cui venga cancellata la prima (ed unica) copia di C, i puntatori ad essa risultano appesi. Per evitare questo, si può introdurre nella copia di C (cioè nella RealSubject) un contatore delle istanze (cioè un contatore dei cloni) in modo tale che la prima copia non possa essere cancellata finché esistono dei puntatori ad essa.

Remote access

Utilizza un remote proxy che fornisce un rappresentante locale di un oggetto posto in un differente spazio di indirizzi.

Si basa sul principio di località secondo il quale se, per esempio, un applicativo legge un pezzo di settore di un disco, probabilmente avrà presto bisogno di leggere il resto del settore. Allora il sistema operativo (che sta in mezzo tra l’applicativo e il disco) usa il meccanismo di buffering, che è un proxy: in corrispondenza della prima richiesta di lettura, il sistema operativo legge tutto il settore ed il suo contenuto viene messo in un buffer; quando l’applicativo legge nuovamente il settore, non legge il disco, ma il buffer.



Figura 45 - diag45.wmf


Il remote access può anche essere utilizzato per gestire l’accesso in rete (cache di file).

Questa gestione consiste nel caricare in memoria, oltre alla pagina visualizzata, anche le pagine alle quali si potrebbe accedere a partire dalla pagina visualizzata. In questo modo viene reso trasparente il caricamento delle pagine e la navigazione diventa più veloce. Tuttavia è possibile che vengano caricate in memoria anche le pagine che non verranno mai visualizzate.



Figura 46 - diag46.wmf


Il pattern Proxy sarà quindi il seguente:

Figura 47 - diag47.gif


Status è una variabile di stato del Proxy; per esempio potrebbe dire se l'immagine completa è già stata caricata in memoria o no.




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


©astratto.info 2017
invia messaggio

    Pagina principale