Newsgroup: it.comp.programmare
Titolo: Pattern Visitor

C'e' qualcuno che mi sa brevemente spiegare che cosa e' il pattern visitor?
Grazie Anticipatamente.
Marco.
--------------------------------
Inviato via 
http://usenet.iol.it

Marco AN wrote:

Viene utilizzato per applicare una o piu' operazioni (algoritmi) ad una 
gerarchia di entita' in maniera flessibile, e senza mutare niente della 
gerarchia che resta immutata. E' utile se hai una gerarchia STABILE di 
entita', alla quale vuoi di volta in volta applicare delle operazioni 
(visite), che possono essere aggiunte e/o tolte in maniera flessibile.
Componenti :
- Una gerarchia di entita' che hanno come superclasse una classe Element 
che definisce un metodo astratto con la seguente signature :
    <quelloCheVuoi> accept(Visitor v);
Tutte le classi che ereditano da Element (ConcreteElement1, 
ConcreteElement2, ...) sovrascrivono il metodo accept nel seguente modo :
    <quelloCheVuoi> accept(Visitor v) {
        v.visit(this);
    }
- Una gerarchia di entita' che hanno come superclasse una classe Visitor 
che definisce un metodo astratto con la seguente signature :
    <quelloCheVuoi> visit(Element e);
Tutte le classi che ereditano da Visitor sovrascrivono il metodo tante 
volte quante sono le classi concrete di Element. Ovvero ogni classe 
concreta di Visitor (ConcreteVisitor1, ConcreteVisitor2, ...) implementano 
l'operazione (algoritmo) che deve essere eseguita sulle istanze delle 
classi concrete di Element :
    <quelloCheVuoi> visit(ConcreteElement1 e1) {... }
    <quelloCheVuoi> visit(ConcreteElement2 e2) {... }
    <quelloCheVuoi> visit(ConcreteElement3 e3) {... }
    ...         
A questo punto puoi avere :
- Una classe che mantiene una lista di oggetti di tipo ConcreteElement*, 
che lui conosce come generici Element, che chiamiamo ObjectVector. Questa 
classe puo' avere un metodo pubblico 
    <quelloCheVuoi> apply(Visitor v)
che non fa altro che chiamare su ogni oggetto di tipo ConcreteElement* che 
contiene, il metodo accept, in questo modo :
    <elementoConcreteElement*>.accept(v);
- Una classe client che conosce gli oggetti di tipo ConcreteVisitor* nella 
loro specifica natura di rappresentati di questa o quell'altra operazione, 
e che conosce ObjectVector.
Ora se il client vuole applicare una determinata operazione, implementata 
da uno dei visitor concreti, non dovra' fare altro che prendere un'istanza 
della classe concreta della gerarchia Visitor che implementa l'operazione, 
e invocare il metodo apply() di ObjectVector con quell'istanza come 
parametro :
    <variabileDelGiustoTipo> =  
         <istanzaDiObjectVector>.apply(<istanzaDiUnConcreteVector>);
Grazie ad un double dipatch tutte le istanze di classi ConcreteElement* 
chiameranno il metodo implementato per loro, relativo alla classe che 
implementa l'operazione richiesta. Infatti
    v.visit(this);
impone un doppio polimorfismo, ovvero una risoluzione della vera natura di 
v che viene visto come generico Visitor, per recuperare la vera natura 
dell'operazione, e quindi il tipo concreto di v che sara' un 
ConcreteVisitor*; e una risoluzione del tipo concreto di this che viene 
visto come generico Element, al fine di recuperare all'interno della classe 
ConcreteVisitor il metodo corretto, implementato per quella classe 
specifica.
ATTENZIONE : <quelloCheVuoi> deve essere un tipo coerente, ovvero devi 
stare attento perche' se il linguaggio che usi e' invariante o parzialmente 
controvariante (come c++), per avere comportamento polimorfico, il tipo di 
ritono e' fondamentale!
ATTENZIONE : La gerarchia degli Element deve essere il piu' stabile 
possibile, infatti ad ogni cambiamento della gerarchia si devono cambiare 
tutte le implementazioni di ConcreteVisitor*. Questo pattern va usato se si 
ha la necessita' di applicare diverse operazioni in maniera flessibile ad 
una gerarchia stabile di entita'.
Se non hai capito una mazza di quello che ho detto (e' difficile spiegarsi 
senza l'ausilio di un diagramma UML, o altro), in rete trovi tanti 
riferimenti, basta che cerchi con google pattern+visitor e vedrai quanto 
trovi. Per tutti i pattern il punto ufficiale dal quale partire e' :
http://hillside.net/patterns/
Ciao
-- 
{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}-{}
SunGray aka Gabriele Lana
contact me @ sungray@tiscalinet
See you space cowboy ...

 (e' difficile spiegarsi  senza l'ausilio di un diagramma UML, o altro)
Parole sante :)
Ciao, Davide.