2010-08-28 5 views
2

Je n'arrive pas à appliquer le modèle de visiteur sur certains objets qui ont des membres scalaires et en même temps des membres agrégés (collections).Implémentation du modèle de visiteur sur les objets agrégés

Ce sont les objets que j'ai:

Artist 
- id 
- name 
- .. more scalar values .. 
- worksOfArt <-- this is a collection as WorkOfArt instances 


WorkOfArt 
- id 
- name 
- .. more scalar values .. 
- artists <-- this is a collection of Artist instances 

Comme vous pouvez le voir, la structure sera également récursive, mais c'est préoccupant plus tard pour moi. ;-)

Ma question est: quelle est la meilleure façon de mettre en œuvre le modèle de visiteur, qui me permet de visiter les objets et aussi seulement leurs enfants visitables (les collections).

Je pensais que la création d'une interface comme ceci:

VisitableAggregateInterface 
{ 
    public function getVisitableChildren(); // this would return only visitable children 
} 

Et puis laissez l'artiste et WorkOfArt étendent une classe abstraite comme ceci:

VisitableAggregateAbstract implements VisitableAggregateInterface 
{ 
    public function accept(Visitor $visitor) 
    { 
     $visitor->visit($this); 
     foreach($this->getVisitableChildren() as $visitableChild) 
     { 
      $visitableChild->accept($visitor); 
     } 
    } 

    /* 
     VisitableAggregateInterface::getVisitableChildren() 
     will be implemented by Artist and WorkOfArt and will only 
     return visitable children (like collections), and not scalar values. 
    */ 
} 

L'objectif ultime est de se retrouver avec un béton Visiteur qui écrira un fichier XML similaire à celui-ci:

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<artgallery> 
    <artists> 
     <artist> 
      <id>1</id> 
      <name></name> 
      <worksOfArt> 
       <workOfArt refid="11"/> 
       <workOfArt refid="12"/> 
      </worksOfArt> 
     <artist> 
    <artists> 
    <worksOfArt> 
     <workOfArt> 
      <id>11</id> 
      <artists> 
       <artist refid="1"/> 
      </artists> 
      <name></name> 
      <info><![CDATA[some info]]></info> 
     </workOfArt> 
     <workOfArt> 
      <id>12</id> 
      <artists> 
       <artist refid="1"/> 
      </artists> 
      <name></name> 
      <info><![CDATA[some info]]></info> 
     </workOfArt> 
    </worksOfArt> 
</artgallery> 

Veuillez nous contacter: Est-ce que je vais dans la bonne direction ici? Parce que l'interface getVisitableChildren() me semble un peu bizarre. Devrais-je peut-être même peut-être abandonner complètement le modèle de visiteur et adopter une approche différente?

Merci.

Répondre

0

Vous n'indiquez pas réellement quelle est la relation entre l'artiste et l'œuvre d'art. Si, comme je le suppose, les deux signifient que l'artiste a créé le WorkOfArt, alors vous n'avez pas de structure de données récursive, vous n'avez donc pas besoin d'un modèle de visiteur.

Je voudrais simplement "force brute" it. Quelque chose comme ça (non testé)

echo "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?> 
<artgallery> 
    <artists>\n"; 
Foreach (Artists as Artist) { 
    echo "  <artist> 
      <id>1</id> 
      <name></name> 
      <worksOfArt>\n"; 
    ForEach (Artist.worksOfArt as Work) { 
     $refid = ????; 
     echo "<workOfArt refid=\"$refid"/>\n"; 
    } 
    echo "  </worksOfArt> 
     </artist>\n"; 
} 
echo " </artists> 
    <worksOfArt>"; 
Foreach (WorkOfArt as work) { 
    ForEach (work.Artists as Artist) { 

    } 
} 

Ensuite, il suffit de mettre le reste des déclarations d'écho dans ce qui précède

BTW - vous avez une faute de frappe dans la question. La fin de et le besoin/s ajouté.

+0

Vous m'avez convaincu de laisser derrière moi le modèle des visiteurs. Je n'étais pas au courant que le modèle de visiteur est généralement destiné à des données récursives. J'ai décidé de suivre l'approche que vous suggérez, même si c'est un peu plus flexible, car j'ai aussi besoin de produire des fragments partiels. Mais vous ne pouviez pas le savoir. Merci. –

1

J'ai vu Visitor implémenté en utilisant une classe 'traverser' qui a une connaissance spécifique des types à visiter. Dans ce cas, il «sait» de visiter WorksOfArt dans Artists mais pas Artists dans WorksOfArt. Vous pouvez définir d'autres traverseurs pour d'autres comportements.

Dan

Voici quelques pseudo-code, je l'ai déterré ... (vb en fait, mais ne dites à personne :)):

visitables:

Public Interface IVisitable 
    Sub accept(ByVal visitor As IVisitor) 
End Interface 

Visiteur :

Public Interface IVisitor 
    Sub visit(ByVal visitable As IVisitable) 
End Interface 

Traverser:

Public Class PaymentListExportTraverser 
    Private payments As PaymentList 
    Private visitor As IVisitor 

    Public Sub New(ByVal paymentList As PaymentList, ByVal exportVisitor As IVisitor) 
     payments = paymentList 
     visitor = exportVisitor 
    End Sub 

    Public Sub traverse() 
     For Each p As Payment In payments 
      p.accept(visitor) 
     Next 
    End Sub 
End Class 
+0

Dan, merci pour votre réponse.Comme j'étais déjà sur la clôture à propos de l'utilisation du modèle de visiteur, Ian m'a convaincu de le laisser derrière moi. Merci quand même. –

+0

Hmm. D'accord. Sachez cependant que Visitor n'est pas spécifique aux structures récursives. –

Questions connexes