Il modello di visitatore non intende estendere la funzionalità di alcune classi. È un pattern che fornisce un modo elegante per operare su alcuni dati (ad esempio per attraversarli) mentre il visitatore può mantenere lo stato e gestire diversi tipi di dati in modo diverso.
Ad esempio, considera uno pseudo-DOM in cui vogliamo raccogliere tutti i titoli, in una lingua con metodi sovraccaricati di tipo:
class CollectHeadlinesVisitor {
List<String> headlines = new List<>();
public void visit(Node n) {
for (Node child in n.childs()) {
this.visit(child);
}
}
public void visit(Headline h) {
list.add(h.text());
for (Node child in n.childs()) {
this.visit(child);
}
}
public List<String> value() {
return headlines;
}
}
Nota che in una lingua senza overload di tipi dobbiamo fare accept
/ visit_Type
indirection.
L'esempio sopra non può essere implementato aggiungendo metodi a Node
e Headline
come spazio necessario per memorizzare i titoli scoperti.
L'aggiunta di metodi alle classi di dati esistenti violerebbe anche il Principio di Responsabilità Unica e potrebbe portare a problemi nello spazio dei nomi, ad es. quando due pezzi di codice ambozzano entrambi alcuni metodi di visitatore. Alcune lingue risolvono questo problema, ma ciò non significa che sia raccomandabile. La sottoclasse non è un'opzione in quanto vogliamo essere in grado di eseguire un nuovo comportamento sui dati esistenti .
L'utilizzo della corrispondenza del modello come nelle lingue derivate da ML non è un'opzione, in quanto non è estensibile (nel mio esempio potrei sottoclasse il visitatore per gestire anche un altro nodo).