2011-08-08 5 views
9

私はプロセスワークアイテムで作業しているアプリケーションです。作業項目の状態に応じて、いくつかのアクションが利用可能です。デザインパターンをお薦めします。

public interface IActionProvider{ 
    public void Complete(WorkItem workItem); 
    public void Cancel (WorkItem workItem); 
    public void Reassign(WorkItem workItem); 
} 

その後の他の詳細に基づいて...

私は現在、次のようになりますインターフェイスを持って行動するための機能を提供するために...など「再割り当て」「キャンセル」「完了」作業項目私はインターフェイスの具体的な実装を持っています。ただ、例...

public class NormalActionProvider :IActionProvider 
{ 
    ... 
} 

public class UrgentActionProvider : IActionProvider 
{ 
    .... 
} 

のための問題は、私は新しいアクション、と言う...「委任」を追加したい場合は、私はもちろんのインタフェースを更新する必要があり、すべての実装に影響を与えます。

これはオープン/クローズの原則に違反していますか?ここで私を助けるかもしれないデザインパターンやリファクタをお勧めできますか?

答えて

11

コマンドパターンのように見えます。より多くのコマンドを変更/追加できます。コマンドクラスは、メインプログラムから切り離されています。

public interface IActionProvider{ 
    public void execute(WorkItem item,ActionType actionType); 
} 

ACTIONTYPEコンプリート表し、その上&をキャンセル。より多くのアクションタイプ&プラグインに適切なコマンドクラスを追加し続けることができます。 「作業項目の状態に応じて、」

0

これは実際にIActionProviderで達成しようとしていることによって異なります。すべての実装が重要と考えるすべてのアクションを実行できるようにするには、実装するインターフェースの一部でなければなりません。インターフェイスは、事前に十分計画されているため、継続的に変更する必要はありません。

しかし、必ずしもすべてのプロバイダがすべてのアクションを実装する必要はありません。良いアドバイスができるようにするには詳細を知っておく必要がありますが、1つの例は、イベントバスに合わせてプロバイダを初期化することです。彼らは気になるイベントに登録し、特定の実装に合ったイベントに対してのみアクションを実行することができます。

3

いつでも、DecoratorをIActionProviderインターフェイスに追加することができます(Decorator design patternに従います)。

0

は、国家デザインパターン

一つの方法または別のものをもたらし、あなたはインターフェイス、最終的にクライアントとの契約を破るリファクタリングする必要があります。

問題を正しく理解していれば、WorkItemProcessorの状態が に変更され、WorkItemが送信されます。

のでごWorkItemProcessorが

// Context 
    public class WorkItemProcessor 
    { 
     public IState CurrentState { get; set; } 

     public WorkItemProcessor(IState initialState) 
     { 
      CurrentState = initialState; 
     } 

     public void Process(WorkItem workItem) 
     { 
      CurrentState.Handle(this, workItem); 
     } 
    } 

その後、我々はWorkItemProcessorが潜在的に

あなたの作業項目がすべてを置くために

// Request 
    public class WorkItem 
    { 
     public bool CompletenessConditionHoldsTrue { get; set; } 

     public bool CancelConditionHoldsTrue { get; set; } 
    } 

のように見えると仮定すると、

// State Contract 
    public interface IState 
    { 
     void Handle(WorkItemProcessor processor, WorkItem item); 
    } 

    // State One 
    public class CompleteState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CompletenessConditionHoldsTrue ? (IState) this : new CancelState(); 
     } 
    } 

    // State Two 
    public class CancelState : IState 
    { 
     public void Handle(WorkItemProcessor processor, WorkItem item) 
     { 
      processor.CurrentState = item.CancelConditionHoldsTrue ? (IState) this : new CompleteState(); 
     } 
    } 

であることができることを、複数の状態を定義なりました一緒に

static void Main() 
    { 
     // Setup context in a state 
     WorkItemProcessor processor = new WorkItemProcessor(new CancelState()); 

     var workItem1 = new WorkItem { CompletenessConditionHoldsTrue = true }; 
     var workItem2 = new WorkItem { CancelConditionHoldsTrue = true }; 

     // Issue requests, which toggles state 
     processor.Process(workItem1); 
     processor.Process(workItem2); 

     Console.Read(); 
    } 

これはあなたをより近づけることを望みます。乾杯。

0

また、コマンドパターンも選択します。拡張として、抽象ファクトリメソッドと組み合わせることができるので、各コマンドクラスのファクトリクラスを持つことができ、それらのファクトリはすべて共通のファクトリインターフェイスを実装します。例えば

// C# 
public interface ICommand { void Execute(); } 

public interface ICommandFactory { ICommand Create(); } 

public class CommandFactoryManager 
{ 
    private IDictionary<string, ICommandFactory> factories; 

    public CommandFactoryManager() 
    { 
     factories = new Dictionary<string, ICommandFactory>(); 
    } 

    public void RegisterCommandFactory(string name, ICommandFactory factory) 
    { 
     factories[name] = factory; 
    } 

    // ... 
} 

この方法で、あなたは動的に新しいコマンドファクトリを登録することができます。たとえば、実行時にDLLをロードし、リフレクションを使用してICommandFactoryインターフェイスを実装するすべてのクラスを取得し、単純なプラグインシステムを使用できます。

関連する問題