Il visitatore è applicabile solo quando si utilizza il pattern Composite?

1

Per molto tempo ho cercato di mettere la mia testa attorno allo schema dei visitatori, e in qualche modo questa cosa continua a essere piuttosto confusa per me.

Attualmente sono sotto l'impressione che sia utile solo applicare le operazioni sugli oggetti che implementano il pattern Composite. Almeno per quanto riguarda PHP. È un'osservazione accurata o mi manca qualcosa?

Sono in procinto di reimplementare alcune funzionalità, e questo include il calcolo di una diff tra due Entità. Queste Entità contengono vari oggetti valore. Derivati diversi nella gerarchia di tipi di queste Entità hanno oggetti di valore diversi. Originariamente il codice diff era contenuto nelle entità stesse, anche se questo ha causato un po 'di confusione, quindi preferirei spostarlo in oggetti di servizio dedicati. Mi è venuta in mente la trama del visitatore, anche se non vedo come possa applicarla in modo sano. Tutti gli oggetti valore devono implementare un'interfaccia EntityElement? Sembra male. È un caso in cui il pattern Visitor non si applica, o semplicemente non riesco a vedere come sarebbe applicato correttamente qui?

    
posta Jeroen De Dauw 22.04.2014 - 12:18
fonte

2 risposte

2

In una lingua strongmente tipizzata, Visitor è utile a causa della "doppia spedizione". Due oggetti di diverso tipo possono interagire senza sapere quali siano i loro tipi. Quindi risolve il "problema dell'handshake": se ho un gruppo di tipi noti, posso avere ogni tipo nel mazzo stringere la mano a ogni altro tipo. La magia che fa è duplice: ti chiamo, passando informazioni importanti senza conoscere il tuo tipo, e poi mi richiami, aggiungendo le tue informazioni. Ora tutti hanno contribuito con la loro parte senza rivelare di che tipo si tratta.

In un linguaggio tipizzato dinamicamente, sono d'accordo che non sembra che ci sia molto da fare. Ci sono modi più semplici per attraversare una struttura di oggetti.

In un linguaggio dinamico, potresti finire con una versione semplificata di Visitor che omette la doppia spedizione.

Nel caso che hai menzionato, diff è un candidato naturale per Visitor, perché ha quel "problema di handshake": hai un sacco di tipi e vuoi diff due di essi. La semplificazione è che ogni classe deve solo avere un metodo diff(other) e un metodo diff(value) . Il trucco è che il valore non deve essere un numero intero - potrebbe essere un tipo più complesso. diff(other) sarebbe appena return other.diff(my_value) . Questa è la parte a doppio invio, che fa il trucco di nascondere gli interni della classe.

...

L'unico altro modello che viene in mente sarebbe un'anima "parametrica del polimorfismo". Hai una classe Diff e ogni classe che hai restituito ha un metodo Diff diff() . La classe Diff contiene qualunque informazione tu abbia bisogno di fare il diff - forse solo un int - ed è una classe comune che estrae i tipi specifici dall'equazione. Quindi sarebbe simile a

Diff d = a.diff().apply(b.diff())

Se Diff contiene davvero solo qualche valore, allora quello che stai facendo è mettere i diversi oggetti su una linea numerica, e potresti semplicemente avere quel valore come una proprietà. Per esempio. a.scale() o a.rank()

    
risposta data 22.04.2014 - 16:17
fonte
0

doOperation() = accept() , Element = Component

La differenza si trova nella ObjectStructure nel diagramma 2. Il pattern Visitor non richiede che ObjectStructure implementa il < < interfaccia > > Componente. (Leggi sotto)

Spesso è utile lasciare che ObjectStructure implementa l'interfaccia Component nel caso in cui si abbia una struttura ad albero o altre collezioni nidificate.

A volte non hai bisogno di una ObjectStructure per implementare l'interfaccia Component. Se ObjectStructure è una raccolta semplice, come un array o un elenco, sai come iterarlo su di esso. Non è necessario aggiungere un metodo accept() a ObjectStructure. È il punto di partenza della tua visita.

    
risposta data 22.04.2014 - 14:57
fonte

Leggi altre domande sui tag