|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
[Java] Implementazione pattern Visitor, qualche domanda e qualche dubbio
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: Codice:
/* 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);
}
Codice:
/* 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);
}
}
Codice:
/* 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);
}
Codice:
/* 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");
}
}
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 |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Sep 2004
Città: Cosenza
Messaggi: 2971
|
1) la differenza è abbastanza netta:
il pattern iterator ti consente di accedere sequenzialmente ad una struttura dati indipendentemente dalla sua rappresentazione interna. il pattern Visitor ti consente invece di eseguire una operazione su elementi di una struttura dati; operazione che operazione che può cambiare senza dover cambiare anche l'oggetto su cui opera, e che può essere diversa per ogni tipo di oggetto. in genere visitor USA iterator 2/3) un main per il tuo esempio è questo (non so se hai il mio stesso pdf..ma l'esempio è uguale..): Codice PHP:
Vector è una struttura dati Java che implementa l'interfaccia Collection e usa un metodo di accesso ai suoi dati simile a quello di un array Ci sono altre strutture dati, LinkedList, ArrayList, etc, sempre già disponibili in Java, che implementano Collection. il main è molto semplice, viene creata una struttura dati (un Vector) nel quale si inserisce una VisitableString successivamente si aggiunge anche un Vector innestato, che contiene a sua volta una VisitableString il motivo per cui può essere aggiunto un vector e questo può essere visitato, non è perchè Vector implementi l'interfaccia Visitable, ma perchè il metodo visit() del nostro ConcreteVisitor (WatcherVisitor) è definito in modo da iterare su una Collection, quindi anche su un Vector: Codice PHP:
l'output del main sarà banalmente: Codice:
'A string' 'Another string' Ultima modifica di deadlyomen17 : 21-05-2010 alle 19:42. |
|
|
|
|
|
#3 |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
Intatnto ri ringrazio però mmm...ok...delle cose ora sono più chiare...delle altre ancora no...
Intato il tuo main non mi gira: Codice:
import java.util.Vector;
public class VisitorExample {
public static void main (String[] arg) {
// Prepare a heterogeneous collection
Vector mainVector = new Vector();
mainVector.add( new VisitableString( "A string" ) );
Vector secondVector = new Vector();
secondVector.add( new VisitableString( "Another string" ) );
mainVector.add(aVector);
mainVector.add(new Double(4));
// Visit the collection
Visitor browser = new WatcherVisitor();
browser.visit( mainVector );
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem: aVector cannot be resolved at VisitorExample.main(VisitorExample.java:15) precisamente a questa riga di codice: Codice:
mainVector.add(aVector); mmm credo ci sia qualcosa che non vada...sai darmi qualche info in più in merito? Grazie mille |
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Sep 2004
Città: Cosenza
Messaggi: 2971
|
avevo dimenticato di modificare quella riga di codice...
questo perchè ho preso il codice da un un'altra parte, e l'ho soltanto modificato e semplificato un po per focalizzare la tua attenzione sul pattern e non sulle minuzie tecniche... mi scuso per questa mia distrazione che ha potuto generare confusione quella riga va cambiata in: Codice:
mainVector.add( secondVector ); edito anche il post precedente per correttezza. oltre a questo, cosa non ti è chiaro? edit: avevo dimenticato anche di spiegarti questa riga: Codice:
mainVector.add(new Double(4)); Ultima modifica di deadlyomen17 : 21-05-2010 alle 19:44. |
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
mmm ora pare che non dia errori ma nella console di eclipse non dà nessun output....dice solo:
<terminated>VisitorsExeple [Java Application] /usr/lib/jvm/java-6-opejdk/bin/java (21/mag/2010 20.19.24) ma non visualizza nessun output....boooo...come mai secondo te? Grazie |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Sep 2004
Città: Cosenza
Messaggi: 2971
|
a questo punto devi spiegarmi tu una cosa...ti interessa la parte pratica o la parte teorico/metodologica del pattern?
in ogni caso ci sono dopo aver controllato il tuo codice, ci sono un paio di errori. il più grosso è nella classe VisitableString...che di visitable non ha nulla visto che non implementa l'interfaccia Visitable... ti basta aggiungere "implements Visitable" e tutto funzionerà...ma credo che più che il semplice errore tecnico, tu debba capire il senso di tutto questo, altrimenti per te resterà un semplice esempio, che fra l'altro si poteva fare ugualmente con una sola classe e pochissime righe di codice. altro piccolo errore: la tua interfaccia Visitor ha un metodo Codice:
visit(Visitable nFloat) avrebbe senso il metodo Codice:
visit( VisitableFloat nFloat ) |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
Quote:
Però se non gira ed ha qualche errore pratico pratico và a finire che mi ci perdo a rifarmi tutti i passaggi :-P Ora provo e vediamo che succede, ti faccio sapere...grazie |
|
|
|
|
|
|
#8 |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
Ancora nada...ora dà 3 errori e vari warnig minori:
Codice:
Description Resource Path Location Type The type WatcherVisitor must implement the inherited abstract method Visitor.visit(VisitableFloat) WatcherVisitor.java /Visitor1/src line 8 Java Problem VisitableFloat cannot be resolved to a type Visitor.java /Visitor1/src line 9 Java Problem VisitableFloat cannot be resolved to a type WatcherVisitor.java /Visitor1/src line 35 Java Problem Collection is a raw type. References to generic type Collection<E> should be parameterized Visitor.java /Visitor1/src line 7 Java Problem Collection is a raw type. References to generic type Collection<E> should be parameterized WatcherVisitor.java /Visitor1/src line 11 Java Problem Collection is a raw type. References to generic type Collection<E> should be parameterized WatcherVisitor.java /Visitor1/src line 24 Java Problem Collection is a raw type. References to generic type Collection<E> should be parameterized WatcherVisitor.java /Visitor1/src line 25 Java Problem Iterator is a raw type. References to generic type Iterator<E> should be parameterized WatcherVisitor.java /Visitor1/src line 13 Java Problem Type safety: The method add(Object) belongs to the raw type Vector. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 9 Java Problem Type safety: The method add(Object) belongs to the raw type Vector. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 12 Java Problem Type safety: The method add(Object) belongs to the raw type Vector. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 14 Java Problem Type safety: The method add(Object) belongs to the raw type Vector. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 16 Java Problem Vector is a raw type. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 8 Java Problem Vector is a raw type. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 8 Java Problem Vector is a raw type. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 11 Java Problem Vector is a raw type. References to generic type Vector<E> should be parameterized VisitorExample.java /Visitor1/src line 11 Java Problem |
|
|
|
|
|
#9 |
|
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Credo vada posta l' attenzione sul fulcro di tale pattern ovvero il double-dispatch realizzato attraverso il metodo:
Codice:
public void accept (Visitor v){
v.visit(this);
}
Va anche aggiunto che di norma il patter Visitor non distingue composite da elementi semplici, per cui solitamente lo start applicativo viene dato mediante il metodo accept e non visit, ma trovandoci nel caso pratico delle Collection come nostro composite (e non avendo tale interfaccia il metodo accept) si può spostare la responsabilità, in partenza su visit. Ultima modifica di nuovoUtente86 : 21-05-2010 alle 21:33. |
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Sep 2004
Città: Cosenza
Messaggi: 2971
|
se solo avessi letto quell'errore...
Codice:
The type WatcherVisitor must implement the inherited abstract method Visitor.visit(VisitableFloat) WatcherVisitor.java /Visitor1/src line 8 Java Problem VisitableFloat cannot be resolved to a type Visitor.java /Visitor1/src line 9 Java Problem ora non per scoraggiarti...ma dovresti impegnarti un attimino e non chiedere per qualsiasi cosa...fra l'altro se usi un qualsiasi IDE per programmare questi errori ti vengono segnalati subito e ti viene anche data la possibilità di risolverli automaticamente a volte solo clicckando su una delle opzioni che ti da... se non conosci le basi di java ti consiglio di valutare l'implementazione dei design pattern in un altro linguaggio che invece conosci. |
|
|
|
|
|
#11 |
|
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
hai perfettamente ragione...devo fare un progetto in Java (che non tocco da più di un anno...)
Si hai ragione...diciamo che dopo una giornata intera di studio stavo bello cotto e non riuscivo a focalizzare...ci penso domani a mente fresca...forse è meglio chiudere il PC dopo tot ore di studio e riprendere quando si è riposati |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 19:26.




















