2009-03-23 11 views
3

私はビジターパターンに関する質問がありますが、現在2つのアセンブリがあります。私の最初のアセンブリはいくつかのインタフェースを含んでいます。訪問者パターン、キャストする必要性を削除

public interface INode 
{ 
    void Visit(INodeVisitor visitor); 
} 

public interface INodeVisitor 
{ 
    void VisitContainer(IContainer container); 
} 

public interface IContainer : INode 
{ 
} 

そして、私の第2組立

class Program 
{ 
    static void Main(string[] args) 
    { 
     ContainerVisitor visitor = new ContainerVisitor(); 
     visitor.VisitContainer(new Container()); 
    } 
} 

public class ContainerVisitor : INodeVisitor 
{ 
    public void VisitContainer(IContainer value) 
    { 
     Container container = value as Container; 
     // Do some stuff... 
    } 
} 

public class Container : IContainer 
{   
    public void Visit(INodeVisitor visitor) 
    { 
     visitor.VisitContainer(this); 
    } 
} 

私は何をしたいContainerVisitorクラスにキャストする必要性を回避されて、私は直接コンテナを参照したいです。コンテナを使用するためにインタフェースINodeVisitorインタフェースを変更することはできません。何か案は?私はちょうどキャストすべきですか?

乾杯

ロハン

答えて

3

キャストは避けられないですが、あなたは、抽象少しそれては、実際のContainerVisitorクラスからそれを削除することができます。

public class NodeVisitor<T> : INodeVisitor where T : IContainer { 
    public void VisitContainer(T node) { 
    var container = node as T; 
    if (container != null) { 
     VisitTyped(container); 
    } 
    } 
    protected abstract VisitContainerTyped(T container); 
} 

今ContainerVisitorがNodeVisitorから派生し、キャスト

public class ContainerVisitor : NodeVisitor<Container>{ 
    protected override void VisitContainerTyped(Container container){ 
     // Do some stuff... 
    } 
} 
1

を避けることができ、私はそれはそれはContainerインスタンスであると仮定することが有効ではないと思います。私は完全に正当な意味で、私自身の​​の実装を書いていて、その実装はそれに挑戦して、インタフェースベースの抽象化の全体を打破しました。あなたが何かのために、オプションのサポートが必要な場合

INodeVisitor visitor = new ContainerVisitor(); 
visitor.VisitContainer(myBespokeContainer); 

:私はインタフェースではなくクラスを使用する可能性があるので、あなたはまた、(有効に)ただ、(​​をサポートするために、明示的な実装を使用して)Containerを受け入れるためのAPIを変更することはできませんベースクラスからは、それを検出するために "as"を使用する必要があります。それ以外のものは抽象を破っています。

1

あなたのIContainerインターフェイスをよりよく定義できない限り、キャストを避けることはできません。そして、Marcが言っているように、それはインタフェースベースの抽象化の目的を破るものです。

public interface IContainer : INode 
{ 
    void Add(IComponent component); 
    void Add(IComponent component, string name); 
    void Remove(IComponent component); 
    ComponentCollection Components { get; } 
} 

より明確に定義されたIContainerでは、訪問者はキャスティングを行う必要はありません。

public class ContainerVisitor : INodeVisitor 
{ 
    public void VisitContainer(IContainer container) 
    { 
     foreach (IComponent component in container.Components) 
     { 
      // ... 
     } 
    } 
} 
関連する問題