2

スカラーメンバーを持ち、同時にメンバー(コレクション)を集約するいくつかのオブジェクトにビジターパターンを適用するのに苦労しています。

これらは私が持っているオブジェクトです:

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

ご覧のとおり、構造も再帰的になりますが、それは後で気になります。;-)

私の質問は、ビジターパターンを実装するための最良の方法は何ですか。これにより、オブジェクトとその訪問可能な子(コレクション)のみを訪問できます。

私はこのようなインターフェースを作成しようと思いました:

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

次に、ArtistとWorkOfArtの両方に次のような抽象クラスを拡張させます。

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.
    */
}

最終的には、次のようなXMLファイルを書き出す具体的なVisitorを作成することが目標です。

<?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>

アドバイスしてください:私はここで正しい方向に進んでいますか?getVisitableChildren()インターフェースが少し風変わりな感じがするからです。おそらく、ビジターパターンを完全に捨てて、別のアプローチを取るべきでしょうか?

ありがとう。

4

2 に答える 2

1

Visitor訪問するタイプの特定の知識を持つ「traverser」クラスを使用して実装されているのを見てきました。WorksOfArtこの場合、訪問することは「知っている」が、でArtistsはない。他の動作のために他のトラバーサーを定義できます。ArtistsWorksOfArt

ダン

これが私が掘り出したいくつかの擬似コードです...(実際にはvbですが、誰にも言わないでください:)):

訪問可能:

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

ビジター:

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

トラバーサー:

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
于 2010-08-28T20:34:38.773 に答える
0

あなたは実際にアーティストとアートワークの関係が何であるかを述べていません。私が思うに、両方ともアーティストがWorkOfArtを作成したことを意味する場合、再帰的なデータ構造がないため、ビジターパターンは必要ありません。

私は単にそれを「ブルートフォース」します。このようなもの(テストされていない)

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) {

   }
}

次に、残りのエコーステートメントを上記に追加します

ところで-あなたは質問にタイプミスがあります。/sの終了と追加が必要です。

于 2010-08-28T23:23:37.480 に答える