e-commerce84
20-05-2010, 18:38
Ciao,
oggi mi stavo studiando il pattern Visitor.
Da quello che ho capito tale pattern serve a visitare ed implementare un'operazione che deve essere eseguita su di una collezione in modo tale che modifiche sull'operazione non implichino modifiche degli elementi su cui essa opera.
Da quello che ho capito è qualcosa di simile ad Iterator solo che la differenza è che con Iterator appunto itera su diversi tipi di collezioni tirando fuori gli elementi uno ad uno in uno specifico modo. Con Visitor invece non è detto che itero ma faccio una specifica operazione in base al tipo di collezione...è giusto o mi sfugge qualcosa?
Comunque...si implementa così:
1) Creo un'interfaccia Visitable che rappresenta un generico oggetto visitabile e che contiene un metodo astratto accept() che di fatto permetterà ad un visitatore di visitare quell'oggetto visitabile.
2) Implemento l'interfaccia Visitable con dei tipi visitabili concreti (che implementano opportunamente il metodo accept() )
3) Creo un'interfaccia Visitor che rappresenta un generico oggetto visitatore e che conterrà un certo numero di metodi visit(TipoConcretoVisitabile) astratti che permetteranno di visitare i vari tipi concreti di oggetti visitabili (ognuno di essi accetta come parametro uno specifico oggetto visitabile concreto)
4) Implemento l'interfaccia Visitor che di fatto implementa i metodi astratti visit() ed attua un comportamento specifico per visitare in uno specifico modo ogni tipo di oggetti visitabile.
Questo è il mio codice (trovato sulle slide e commentato da me...)
1) Interfaccia Visitable:
/* Interfaccia che rappresenta generici oggetti visitabili che verranno poi
* raggruppati in collezioni visitabili */
public interface Visitable {
/* Metodo che consente ad un visitatore concreto di essere "accettato */
public void accept(Visitor visitor);
}
2) Una classe che implementa Visitable:
/* Classe che implementa l'interfaccia Visitable e che rappresenta stringhe
* visitabili */
public class VisitableString {
private String value;
// CREATORE:
public VisitableString(String string){
value = string;
}
// Restituisce al chiamante il valore della stringa:
public String getString(){
return value;
}
/* IMPLEMENTAZIONE DEL METODO accept() DELL'INTERFACCIA CHE PERMETTE DI
* VISITARE L'OGGETTO IN QUESTIONE: come parametro di input riceve il
* riferimento ad un generico oggetto visitor */
public void accept(Visitor visitor){
/* Invia al visitor ricevuto nel parametro il messaggio di visitare
* l'oggetto Visitable corrente */
visitor.visit(this);
}
}
3) Interfaccia Visitor:
/* Interfaccia che rappresenta un generico oggetto visitatore che può visitare o
* oggetti di tipo Collection, o oggetti di tipo VisitableString, o oggetti di tipo
* nFloat */
import java.util.Collection;
public interface Visitor {
public void visit(Collection collection);
public void visit(VisitableString string);
public void visit(Visitable nFloat);
}
4) Una classe che implementa Visitor
/* Classe concreta che implementa l'interfaccia Visitor e che realizza un oggetto
* visitatore di oggetti di tipo Collection o di tipo VisitableString o di tipo
* VisitableFloat */
import java.util.Collection;
import java.util.Iterator;
public class WatcherVisitor implements Visitor {
/* Metodo che visita una collezione di oggetti di tipo Collection */
public void visit(Collection collection){
// Crea un iteratore sulla collezione ricevuta come parametro di input
Iterator iterator = collection.iterator();
while(iterator.hasNext()){ // Finchè ci sono ancora elementi da visitare
Object o = iterator.next(); // Mette l'elemento corrente in o
if(o instanceof Visitable) // Se o è un oggetto visitabile
/* o da Object viene castato a generico Visitable e su di esso
* viene invocato il metodo accept() di Visitable che in base al
* suo tipo effettivo passandogli l'oggetto visitor corrente come
* parametro */
((Visitable)o).accept(this);
else if(o instanceof Collection) // Se o è un oggetto Collection
visit((Collection) o); // Invoca visit() passandogli la collezione
}
}
/* Metodo che visita un oggetto di tipo VisitableString */
public void visit(VisitableString vString){
System.out.println("'" + vString.getString() + "'");
}
/* Metodo che visita un oggetto di tipo VisitableFloat */
public void visit(VisitableFloat vFloat){
System.out.println(vFloat.getFloat().toString() + "f");
}
}
Credo di aver capito a grandi linee come funziona ma ho vari dubbi:
1) Analogie e differenze tra Visitor ed Iterator?
2) A grandi linee il funzionamento di questo pattern da quello che ho capito è il seguente: in un ipotetico main() dichiaro e creo un oggetto visitabile (che implementa l'interfaccia Visitable). Poi che faccio? Creo un oggetto Visitor per l'oggetto visitabile? su tale ogetto visitabile chiamo il metodo accept passandogli il riferimento all'oggetto Visitor creato. A questo punto il metodo accept chiamerà il metodo visit() (del visitor passatogli come parametro) passandogli il rifferimento all'oggetto visitabile corrente. A questo punto l'oggetto visitatore invocherà il corretto metodo visit() in base al tipo effettivo dell'oggetto da visitare ricevuto come parametro di input ed in base al suo tipo effettivo lo visiterà in un certo modo. Come discorso è corretto o ho fatto un gran casino?
2) Nel mio esempio ho implementato solo uno dei 3 possibili tipi di oggetti visitabili (VisitableString), l'altro di tipo Collection dovrebbe già essere fornito da Java in quanto lo importo, giusto?
Grazie
oggi mi stavo studiando il pattern Visitor.
Da quello che ho capito tale pattern serve a visitare ed implementare un'operazione che deve essere eseguita su di una collezione in modo tale che modifiche sull'operazione non implichino modifiche degli elementi su cui essa opera.
Da quello che ho capito è qualcosa di simile ad Iterator solo che la differenza è che con Iterator appunto itera su diversi tipi di collezioni tirando fuori gli elementi uno ad uno in uno specifico modo. Con Visitor invece non è detto che itero ma faccio una specifica operazione in base al tipo di collezione...è giusto o mi sfugge qualcosa?
Comunque...si implementa così:
1) Creo un'interfaccia Visitable che rappresenta un generico oggetto visitabile e che contiene un metodo astratto accept() che di fatto permetterà ad un visitatore di visitare quell'oggetto visitabile.
2) Implemento l'interfaccia Visitable con dei tipi visitabili concreti (che implementano opportunamente il metodo accept() )
3) Creo un'interfaccia Visitor che rappresenta un generico oggetto visitatore e che conterrà un certo numero di metodi visit(TipoConcretoVisitabile) astratti che permetteranno di visitare i vari tipi concreti di oggetti visitabili (ognuno di essi accetta come parametro uno specifico oggetto visitabile concreto)
4) Implemento l'interfaccia Visitor che di fatto implementa i metodi astratti visit() ed attua un comportamento specifico per visitare in uno specifico modo ogni tipo di oggetti visitabile.
Questo è il mio codice (trovato sulle slide e commentato da me...)
1) Interfaccia Visitable:
/* Interfaccia che rappresenta generici oggetti visitabili che verranno poi
* raggruppati in collezioni visitabili */
public interface Visitable {
/* Metodo che consente ad un visitatore concreto di essere "accettato */
public void accept(Visitor visitor);
}
2) Una classe che implementa Visitable:
/* Classe che implementa l'interfaccia Visitable e che rappresenta stringhe
* visitabili */
public class VisitableString {
private String value;
// CREATORE:
public VisitableString(String string){
value = string;
}
// Restituisce al chiamante il valore della stringa:
public String getString(){
return value;
}
/* IMPLEMENTAZIONE DEL METODO accept() DELL'INTERFACCIA CHE PERMETTE DI
* VISITARE L'OGGETTO IN QUESTIONE: come parametro di input riceve il
* riferimento ad un generico oggetto visitor */
public void accept(Visitor visitor){
/* Invia al visitor ricevuto nel parametro il messaggio di visitare
* l'oggetto Visitable corrente */
visitor.visit(this);
}
}
3) Interfaccia Visitor:
/* Interfaccia che rappresenta un generico oggetto visitatore che può visitare o
* oggetti di tipo Collection, o oggetti di tipo VisitableString, o oggetti di tipo
* nFloat */
import java.util.Collection;
public interface Visitor {
public void visit(Collection collection);
public void visit(VisitableString string);
public void visit(Visitable nFloat);
}
4) Una classe che implementa Visitor
/* Classe concreta che implementa l'interfaccia Visitor e che realizza un oggetto
* visitatore di oggetti di tipo Collection o di tipo VisitableString o di tipo
* VisitableFloat */
import java.util.Collection;
import java.util.Iterator;
public class WatcherVisitor implements Visitor {
/* Metodo che visita una collezione di oggetti di tipo Collection */
public void visit(Collection collection){
// Crea un iteratore sulla collezione ricevuta come parametro di input
Iterator iterator = collection.iterator();
while(iterator.hasNext()){ // Finchè ci sono ancora elementi da visitare
Object o = iterator.next(); // Mette l'elemento corrente in o
if(o instanceof Visitable) // Se o è un oggetto visitabile
/* o da Object viene castato a generico Visitable e su di esso
* viene invocato il metodo accept() di Visitable che in base al
* suo tipo effettivo passandogli l'oggetto visitor corrente come
* parametro */
((Visitable)o).accept(this);
else if(o instanceof Collection) // Se o è un oggetto Collection
visit((Collection) o); // Invoca visit() passandogli la collezione
}
}
/* Metodo che visita un oggetto di tipo VisitableString */
public void visit(VisitableString vString){
System.out.println("'" + vString.getString() + "'");
}
/* Metodo che visita un oggetto di tipo VisitableFloat */
public void visit(VisitableFloat vFloat){
System.out.println(vFloat.getFloat().toString() + "f");
}
}
Credo di aver capito a grandi linee come funziona ma ho vari dubbi:
1) Analogie e differenze tra Visitor ed Iterator?
2) A grandi linee il funzionamento di questo pattern da quello che ho capito è il seguente: in un ipotetico main() dichiaro e creo un oggetto visitabile (che implementa l'interfaccia Visitable). Poi che faccio? Creo un oggetto Visitor per l'oggetto visitabile? su tale ogetto visitabile chiamo il metodo accept passandogli il riferimento all'oggetto Visitor creato. A questo punto il metodo accept chiamerà il metodo visit() (del visitor passatogli come parametro) passandogli il rifferimento all'oggetto visitabile corrente. A questo punto l'oggetto visitatore invocherà il corretto metodo visit() in base al tipo effettivo dell'oggetto da visitare ricevuto come parametro di input ed in base al suo tipo effettivo lo visiterà in un certo modo. Come discorso è corretto o ho fatto un gran casino?
2) Nel mio esempio ho implementato solo uno dei 3 possibili tipi di oggetti visitabili (VisitableString), l'altro di tipo Collection dovrebbe già essere fornito da Java in quanto lo importo, giusto?
Grazie