2

列挙型 (ドメイン層に含まれる) をポリモーフィック クラスにリファクタリングする場合、リファクタリングするすべての switch および if ステートメントが他の層 (これは、ドメイン層内でこれらの層を参照することになる可能性があるためです。

public abstract class MyRefactoredEnum
{
    public abstract void DoSomething(IBusinnessObject aBizObject); //dependency to the biz. layer

    public abstract MvcHtmlString GetImgTag(); //dependency to presentation layer
}

(上記の例では、「相互参照」の問題も発生する可能性があります)

ビジター パターン ( http://en.wikipedia.org/wiki/Visitor_pattern ) がこの問題の有効な解決策であることがわかりました。ドメイン レイヤーでは MyRefactoredEnum.IVisitor インターフェースのみを定義し、他のすべてのレイヤーは独自の訪問者を実装します。

唯一の問題: MyRefactoredEnum.IVisitor インターフェイスを変更する場合 (たとえば、別の MyRefactoredEnum のサブクラスを追加したため)、ドメイン モデルを参照するすべてのプロジェクトとソリューションを変更して再コンパイルする必要があります。リフレクション ( http://surguy.net/articles/visitor-with-reflection.xml ) を使用して問題を解決できますが、遅くなる可能性があります...

列挙型をリファクタリングするためのより良いパターンはありますか?

PS: 私のひどい英語でごめんなさい :)

4

1 に答える 1

5

フォールバック メソッドを持つ訪問者にデフォルトの実装を提供できます。

abstract class Cheese
{
    public abstract void Visit(ICheeseVisitor visitor);
}

class Wensleydale : Cheese { ... }

class Gouda : Cheese { ... }

interface ICheeseVisitor
{
    void Visit(Wensleydale cheese);
    void Visit(Gouda cheese);
}

abstract class CheeseVisitor : ICheeseVisitor
{
    public virtual void Visit(Wensleydale cheese) { Default(cheese); }
    public virtual void Visit(Gouda cheese) { Default(cheese); }
    public virtual void Default(Cheese cheese) { }
}

新しい型を追加すると、古いバージョンに対してビルドされたライブラリはフォールバック メソッドを使用しますが、新しいライブラリは新しいオーバーロードをオーバーライドできます。

class Brie
{
    public override void Visit(ICheeseVisitor visitor)
    {
        visitor.Visit(this);
    }
}

interface ICheeseVisitor
{
    ...
    void Visit(Brie cheese);
}

abstract class CheeseVisitor : ICheeseVisitor
{
    ...
    public virtual void Visit(Brie cheese) { Default(cheese); }
    ...
}

例:

class CheeseImgVisitor : CheeseVisitor 
{
    private string src;

    public string Src
    {
        get { return this.src; }
    }

    public override void Visit(Wensleydale cheese)
    {
        this.src = "wensleydale.png";
    }

    public override void Visit(Gouda cheese)
    {
        this.src = "gouda.png";
    }

    public override void Default(Cheese cheese)
    {
        this.src = "generic_cheese.png";
    }
}
于 2010-08-28T12:43:26.730 に答える