2009-05-07 14 views
5

私の同僚がプログラムロジックを制御するために 'マーカークラス'を使用していることがわかりました(下記の設計例を参照)。うまく動作しているようだ、とコードが本当にうまく読みますが、臭いそれについてだけで何か...マーカークラスを使用してロジックフローを制御する

namespace ConsoleApplication4983 
{ 
    public class MyClass 
    { 
     static void Main() 
     { 
      var c = new MyClass(); 
      c.DoSomething(new Sequential()); 
      c.DoSomething(new Random()); 
     } 

     public void DoSomething(ProcessingMethod method) 
     { 
      if (method is Sequential) 
      { 
       // do something sequential 
      } 
      else if (method is Random) 
      { 
       // do something random 
      } 
     } 
    } 

    public class ProcessingMethod {} 
    public class Sequential : ProcessingMethod {} 
    public class Random : ProcessingMethod {} 
} 

は、同じ効果を達成するためのより良い方法だろう何がありますか?列挙型?属性?彼らはより多くの柔軟性を提供してインターフェース

答えて

8

マーカーは、より良い練習です。

しかし、この特定のケースでは、仮想ディスパッチがより良い解決策であると私は思っています。

using System; 

namespace ConsoleApplication4983 
{ 
    public class MyClass 
    { 
     static void Main() 
     { 
      var c = new MyClass(); 
      c.DoSomething(new Sequential()); 
      c.DoSomething(new Random()); 
     } 

     public void DoSomething(ProcessingMethod method) 
     { 
      method.Foo(); 
     } 
    } 

    public class ProcessingMethod 
    { 
     public virtual void Foo() { } 
    } 
    public class Sequential : ProcessingMethod 
    { 
     public override void Foo() { } 
    } 
    public class Random : ProcessingMethod 
    { 
     public override void Foo() { } 
    } 
} 
1

彼はほとんどそこにいましたが、それほどではありませんでした。それはおそらくあなたが見ているものです。型のif文は悪臭です。 ProcessingMethod基底クラスに何かがあったはずであり、拡張された各型は独自のバージョンを持つべきです。

public void DoSomething(ProcessingMethod method) { 
    method.DoSomething(); 
} 
0

どのように処理ロジックを特定のサブクラスに委任しますか? ProcessingMethodには、各サブクラスによって実装される抽象メソッドがあります。

public void DoSomething(ProcessingMethod method) 
{ 
    method.Process(); 
} 

public abstract class ProcessingMethod 
{ 
    public abstract void Process(); 
} 

public class Sequental : ProcessingMethod 
{ 
    public override void Process() 
    { 
    // do something sequential 
    } 
} 

public class Random : ProcessingMethod 
{ 
    public override void Process() 
    { 
    // do something random 
    } 
} 
0

ええ、これは悪いです。並列処理をしたい場合:

public class Parallel : ProcessingMethod{} 

あなたは多くのコードを変更する必要があります。

4

あなたがしたいのは、これをstrategy patternに置き換えることです。戦略は、何がどのように行われるか、すなわちアルゴリズムを定義する。私はProcessingMethodの新しいタイプを持っている場合

public interface IProcessingMethod 
{ 
    void Process(); 
} 

public class SequentialProcess : IProcessingMethod 
{ 
    public void Process(IProcessable obj) 
    { 
     do something sequentially with the obj 
    } 
} 

public class ParallelProcess : IProcessingMethod 
{ 
    public void Process(IProcessable obj) 
    { 
     do something in parallel with the obj 
    } 
} 

public interface IProcessable 
{ 
    void Process(IProcessingMethod method); 
} 

public class MyClass : IProcessable 
{ 
    public void Process(IProcessingMethod method) 
    { 
     method.Process(this); 
    } 
} 

... 

var obj = new MyClass(); 
obj.Process(new SequentialProcess()); 

は今、私は単純にそのメソッドのクラスを作成し、処理方法は、私のIProcessableオブジェクトの処理方法に注入されたものを決定するコードを変更する必要があります。

+0

+1これは良いアプローチです。 –

0

フレームワークデザインガイドラインでは、マーカーインターフェイス(およびおそらくマーカークラス)を使用することをお勧めします。あなたが行ったように、isを使用することは、反射を使って属性をチェックするよりもはるかに迅速であると言っています。

2

私はこの質問が古いことを知っていますが、私はすべての答えがポイントを逃したと感じています。

例が必要な機能の範囲を完全に示す場合、ここで使用する適切な構成は列挙型です。 Enum型は値型です。基本的に数値定数のように機能し、優れたIDEオートコンプリートをサポートします。 Enum型を使用するように変更された例を次に示します。

namespace ConsoleApplication4983 
{ 
    public class MyClass 
    { 
     static void Main() 
     { 
      var c = new MyClass(); 
      c.DoSomething(ProcessingMethod.Sequential); 
      c.DoSomething(ProcessingMethod.Random); 
     } 

     public void DoSomething(ProcessingMethod method) 
     { 
      if (method == ProcessingMethod.Sequential) 
      { 
       // do something sequential 
      } 
      else if (method == ProcessingMethod.Random) 
      { 
       // do something random 
      } 
     } 
    } 

    public enum ProcessingMethod 
    { 
     Sequential, 
     Random 
    } 
} 

その他の回答は、より複雑なパターンを参照しています。私は彼らが "マーカークラス"という言葉にあまりにも多くを読んだと思う。時には、戦略パターンや仮想ディスパッチなどが良い方法ですが、この場合、このコードにはEnumが最も簡単な改善点だと思います。

関連する問題