La pro­gram­ma­zio­ne orientata agli oggetti (OOP), che viene clas­si­fi­ca­ta come sot­to­se­zio­ne del paradigma di pro­gram­ma­zio­ne im­pe­ra­ti­vo ha assunto molta im­por­tan­za negli ultimi anni. L’opzione di de­scri­ve­re tutte le com­po­nen­ti di un progetto software come oggetto, il cui com­por­ta­men­to può essere definito tramite le relative classi, offre dei vantaggi decisivi rispetto ad altri stili di pro­gram­ma­zio­ne. So­prat­tut­to la pos­si­bi­li­tà di poter riu­ti­liz­za­re com­po­nen­ti di programma senza alcun problema è un argomento decisivo che porta molti svi­lup­pa­to­ri a decidere di uti­liz­za­re la OOP.

Per rendere ancora più semplice questa riu­sa­bi­li­tà, così come l’im­ple­men­ta­zio­ne e la pos­si­bi­li­tà di ef­fet­tua­re dei test degli oggetti in­cor­po­ra­ti, i modelli di pro­get­ta­zio­ne GoF sono stati pre­sen­ta­ti nel libro “Design Patterns: Elements of Reusable Object Oriented Software”. Tra questi oltre 20 design pattern troviamo anche il co­sid­det­to Visitor pattern o Visitor design pattern (in italiano: schema pro­get­tua­le di vi­si­ta­to­re), che verrà det­ta­glia­ta­men­te descritto nei seguenti paragrafi.

Cos’è il Visitor pattern?

Il Visitor design pattern, in breve Visitor pattern, rap­pre­sen­ta un modello ri­so­lu­ti­vo per separare un algoritmo dalla struttura di oggetti a cui è applicato. Descrive un modo per inserire nuove ope­ra­zio­ni in strutture di oggetti pre­e­si­sten­ti, senza che queste strutture debbano essere mo­di­fi­ca­te per questo. Grazie a questa proprietà, il Visitor pattern rap­pre­sen­ta una possibile opzione per l’ap­pli­ca­zio­ne del principio aperto/chiuso (OCP). Questo principio dello sviluppo software orientato agli oggetti si basa sul fatto che le unità software, come moduli, classi o metodi, sono con­tem­po­ra­nea­men­te aperte (open) per delle esten­sio­ni e chiuse (closed) alle modifiche.

Il Visitor pattern è uno dei 23 modelli di pro­get­ta­zio­ne (categoria: modello com­por­ta­men­ta­le descritti e pub­bli­ca­ti nel 1994 dagli in­for­ma­ti­ci Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides. Dato che i quattro sono co­no­sciu­ti nel mondo degli svi­lup­pa­to­ri anche come “Gang of Four”, ab­bre­via­to in GoF, per il suddetto pattern è stato coniato il nome di schema pro­get­tua­le GoF.

Qual è lo scopo del Visitor design pattern?

Se la struttura a oggetti è composta da molte classi slegate tra loro con una costante richiesta di nuove ope­ra­zio­ni, è difficile per lo svi­lup­pa­to­re dover im­ple­men­ta­re una nuova sot­to­clas­se per ogni nuova ope­ra­zio­ne. Il risultato è un sistema con diverse classi di nodi, difficile non solo da capire ma anche da mantenere e mo­di­fi­ca­re. L’istanza decisiva del Visitor pattern, il vi­si­ta­to­re (visitor), permette di ag­giun­ge­re nuove funzioni virtuali a una famiglia di classi, senza dover mo­di­fi­ca­re queste ultime.

N.B.

Le funzioni virtuali o metodi de­fi­ni­sco­no le funzioni obiettivo ese­gui­bi­li, per le quali non è ne­ces­sa­rio che l’obiettivo sia già co­no­sciu­to al momento della com­pi­la­zio­ne. Rap­pre­sen­ta­no uno strumento im­por­tan­te della lingua orientata agli oggetti.

Lo schema pro­get­tua­le di vi­si­ta­to­re prevede che un tale oggetto vi­si­ta­to­re abbia una de­fi­ni­zio­ne separata, con l’obiettivo di im­ple­men­ta­re un’ope­ra­zio­ne eseguita su un elemento o più elementi della struttura di oggetti. I client che hanno accesso alla struttura di oggetti ri­chia­ma­no il relativo metodo di elementi come “accept(visitor)”, che delegano la richiesta all’oggetto vi­si­ta­to­re accettato. Ne consegue che l’oggetto vi­si­ta­to­re può eseguire la relativa ope­ra­zio­ne.

Rap­pre­sen­ta­zio­ne grafica del Visitor pattern (diagramma UML)

L’in­te­ra­zio­ne tra gli elementi dati e gli oggetti vi­si­ta­to­ri inclusi secondo il Visitor design pattern può essere spiegata al meglio con una rap­pre­sen­ta­zio­ne grafica delle relazioni e delle procedure di un possibile software orientato agli oggetti. A tal fine è perfetto il lin­guag­gio di mo­del­la­zio­ne UML (Unified Modeling Language), che per questo motivo è stato uti­liz­za­to anche nel seguente diagramma di classi per il Visitor pattern.

I vantaggi e gli svantaggi del Visitor pattern

Il Visitor pattern rap­pre­sen­ta una via già col­lau­da­ta e ben fun­zio­nan­te per estendere delle unità esistenti di un software orientato agli oggetti. In caso si debba ag­giun­ge­re una nuova ope­ra­zio­ne, si può procedere tran­quil­la­men­te tramite la de­fi­ni­zio­ne di un nuovo vi­si­ta­to­re. Questo modo di procedere consente inoltre di cen­tra­liz­za­re ogni codice fun­zio­na­le: la relativa im­ple­men­ta­zio­ne di un’ope­ra­zio­ne si trova cen­tral­men­te nella classe vi­si­ta­to­re e non deve essere com­ple­ta­ta in aggiunta nelle altre singole classi. Il vantaggio chiave di un software con il Visitor design pattern insomma, sta nel fatto che il codice sorgente alla base degli oggetti uti­liz­za­ti non deve essere co­stan­te­men­te adeguato. La logica si suddivide invece tra il vi­si­ta­to­re, che agisce come sostituto, e le classi di vi­si­ta­to­ri.

Na­tu­ral­men­te anche lo schema pro­get­tua­le di vi­si­ta­to­re non è perfetto in ogni suo punto. Chi lavora secondo i principi di questo modello deve essere con­sa­pe­vo­le che anche a seguito di minime modifiche alla classe di un elemento, nella maggior parte dei casi sono necessari ade­gua­men­ti anche nelle classi di vi­si­ta­to­ri at­tri­bui­te. Inoltre, non si risparmia lavoro ag­giun­ti­vo per la suc­ces­si­va in­tro­du­zio­ne di nuovi elementi, perché anche per questi vanno im­ple­men­ta­ti metodi vi­si­ta­to­re, che a loro volta si devono integrare nelle classi Con­cre­te­Vi­si­tor. L’ec­cel­len­te pos­si­bi­li­tà di ampliare le unità di software è legata ad un certo impegno.

Dove si utilizza il Visitor pattern?

Il Visitor design pattern può sem­pli­fi­ca­re no­te­vol­men­te i compiti ri­cor­ren­ti nello sviluppo di software. So­prat­tut­to per gli svi­lup­pa­to­ri che seguono il paradigma di pro­gram­ma­zio­ne orientato agli oggetti, sarebbe utile con­fron­tar­si con questo schema pro­get­tua­le. Dalla sua pre­sen­ta­zio­ne nel 1994, il modello si è affermato nell’ambiente di pro­gram­ma­zio­ne, e il tipo di progetto software non svolge un ruolo decisivo in linea di massima per il fattore d’uso del pattern. Anche re­la­ti­va­men­te ai linguaggi di pro­gram­ma­zio­ne che ne traggono vantaggio, non ci sono li­mi­ta­zio­ni concrete di base per il principio di mo­del­la­zio­ne, a meno che sia stato tarato in modo par­ti­co­la­re per il paradigma orientato agli oggetti.

Il Visitor pattern svolge un ruolo ele­men­ta­re tra gli altri nei seguenti popolari linguaggi di pro­gram­ma­zio­ne:

  • C++
  • C#
  • Java
  • PHP
  • Python
  • Ja­va­Script
  • Golang
iueor-qViR4.jpg Per visualizzare questo video, sono necessari i cookie di terze parti. Puoi accedere e modificare le impostazioni dei cookie qui.

Esempi pratici dell’impiego del Visitor pattern

Non è per niente semplice capire i vantaggi e lo scopo del Visitor pattern per un os­ser­va­to­re esterno. Ma chi studia pro­gram­ma­zio­ne viene au­to­ma­ti­ca­men­te a contatto con la mo­del­la­zio­ne e la sua ap­pli­ca­zio­ne.

Per creare un’analogia con la vita reale, per il Visitor pattern si utilizza spesso l’esempio di un viaggio in taxi: un cliente prenota un taxi che arriva, su richiesta, fino alla porta di casa sua. Una volta che la persona è seduta all’interno del taxi “in visita”, quest’ultimo (o il tassista) è com­ple­ta­men­te re­spon­sa­bi­le del trasporto della persona.

Spesso per il­lu­stra­re il fun­zio­na­men­to del Visitor pattern si usa anche l’immagine della spesa al su­per­mer­ca­to: la persona che deve ef­fet­tua­re gli acquisti mette nel carrello ciò che desidera comprare, che me­ta­fo­ri­ca­men­te rap­pre­sen­ta il set di elementi della struttura di oggetti. Una volta alla cassa, il cassiere è il vi­si­ta­to­re, che scansiona i prezzi e il peso dei singoli prodotti (o elementi) scelti, per calcolare il costo finale.

Esempio di codice secondo l’approccio Visitor pattern (PHP)

In ultimo vi pre­sen­tia­mo il seguente codice, una semplice ap­pli­ca­zio­ne del Visitor pattern in PHP.

return 'B';
	}
	public function getData() {
		return $this->the_data;
	}
	publicfunction accettare(Visitatore $visitatore) {
		$visitatore->VisitaDiElementoB($this);
	}
}
abstract class visitatore {
	abstract function VisitaDiElementoA(ElementoA $elem);
	abstract function VisitaDiElementoB(ElementoB $elem);
}
class Visitatore1 extends Visitatore {
	private $characteristics;
	public function getCharacs() {
		return $this->characteristics;
	}
	public function VisitaDiElementoA(ElementoA $elem) {
		$this->characteristics = 'Info:'.$elem->getInfo();
	}
	abstract function VisitaDiElementoB(ElementoB $elem){
		$this->characteristics = 'DATA:'.$elem->getData().'!!';
	}
}
function Test() {
	write_line('InizioTesto');
	// Struttura di oggetti
	$elementi = array (
		newElementoA('Ciao', 'Nuovo!!'),
		newElementoB('Finalmente.'),
	);
	$bes1 = nuovo visitatore1();
	foreach ($elementi as $elemento) {
		$elemento->accettare($bes1);
		write_line('Dopo la visita di elemento '.$elemento->getName().': '.$bes1-			>getCharacs());
}
}
functionwrite_line($text) {
	print $text.'<br>';
}
Test();

L’output di questo snippet di codice esempio appare come segue:

Inizio testo
Dopo la visita di elemento A: Info:[Ciao--Nuovo!!]
Dopo la visita di elemento B: DATA:(Finalmente.)!!
Vai al menu prin­ci­pa­le