0

次のようなインターフェースを使用した訪問者パターンの実装では (インターフェース自体が間違っていると思われる場合はお気軽に教えてください)、訪問したすべてのアイテムのリストを追跡する責任は誰にありますか? ビジターかビジタブルか?具体的には、トラッカーは、同じアイテムが 2 回アクセスされないようにする必要もあります (アクセスしているグラフに循環参照が含まれている場合)。

/// <summary>
/// Defines a type that may accept visitors.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IVisitable<T>
{
    // Methods
    void Accept(T instance, IVisitor<T> visitor);
}

/// <summary>
/// Defines a type that visits objects.
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IVisitor<T>
{
    // Methods
    void Visit(IVisitable<T> visitable);

    // Properties
    bool HasCompleted { get; }
}
4

1 に答える 1

3

訪問者は、訪問したすべてのアイテムを追跡する必要があります。IVisitable訪問者は、訪問できることだけを知っているのとは異なり、訪問したものを常に認識しています。

他のソリューションは結合を増加させます。

インターフェイスとして、次のように変更します。

public interface IVisitable<T>
{
    void Accept(IVisitor<T> visitor);
}

public interface IVisitor<T>
{
    bool Visit(T item);
}

これは、訪問者が同じアイテムを複数回処理しない場合、訪問したアイテムのリストを保持する必要があることを意味します。

public class MyVisitor : IVisitor<TheItem>
{
    private List<TheItem> _visitedItems = new List<TheItem>();

    public bool Visit(TheItem item)
    {
         if (_visitedItems.Contains(item)) return true;
         _visitedItems.Add(item);

         //process here. Return false when iteration should be stopped.
    }
}

public class MyItems : IVisitable<TheItem>
{

     public void Accept(IVisitor<TheItem> visitor)
     {
         foreach (var item in items)
         {
             if (!visitor.Visit(item))
                 break;
         }
     }
}

更新 2

IEnumerable(イテレータ) は、実際にはビジター パターンの進化形です。違いは、訪問したクラスの内側から外側にループを移動することです。

アップデート 3

リストを作成し、次のステートメントを使用しList<MyItem> items = new List<MyItem>();てそれを繰り返すことができます (インターフェースを使用します):foreachIEnumerable<T>

foreach (var item in items)
{
    //do anything here. use `break` to exit loop.
}

それは次と同じです:

var enumerator = items.GetEnumerator();
while (enumerator.MoveNext())
{
    Console.WriteLine("The item: " + enumerator.Current);
}
于 2011-01-18T11:12:35.813 に答える