8

私が取り組んでいるアプリケーションは、作業項目を処理します。ワークアイテムの状態に応じて、利用可能なアクションがいくつかあります。「完了」「キャンセル」「再割り当て」など…

アクションの機能を提供するために、私は現在、次のようなインターフェースを持っています...

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
{
   ....
}

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

これはオープン/クローズの原則に違反していますか? ここで役立つと思われるデザインパターンまたはリファクタリングをお勧めできますか?

4

5 に答える 5

11

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

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

ActionType は、完了、キャンセルなどを表します。より多くのアクション タイプとプラグインの適切なコマンド クラスを追加し続けることができます。

于 2011-08-08T03:29:57.103 に答える
3

IActionProvider インターフェイスにいつでも Decorator を追加できます ( Decorator デザイン パターンに従ってください)。

于 2011-08-08T03:16:18.030 に答える
0

「ワークアイテムの状態に応じて」状態設計パターンをもたらす

何らかの方法で、インターフェイスをリファクタリングし、最終的にクライアント コントラクトを破棄する必要があります。

私があなたの問題を正しく理解していれば、WorkItemProcessor に送信された WorkItem に応じて状態が変化する WorkItemProcessor があります。

したがって、 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 が潜在的に存在する可能性のある複数の状態を定義します。

// 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();
        }
    }

WorkItemが次のように見えると仮定します

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

         public bool CancelConditionHoldsTrue { get; set; }
    }

すべてをまとめるには

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();
    }

これがあなたに近づくことを願っています。乾杯。

于 2011-08-08T04:46:28.937 に答える
0

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

しかし、必ずしもすべてのアクションをすべてのプロバイダーで実装する必要はないようです。適切なアドバイスを行うには、詳細を知る必要がありますが、1 つの例として、プロバイダーが一種のイベント バスに対して自分自身を初期化することが挙げられます。関心のあるイベントをサブスクライブし、特定の実装にとって意味のあるイベントに対してのみアクションを実行できます。

于 2011-08-08T03:06:37.987 に答える
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 インターフェイスを実装するすべてのクラスを取得でき、シンプルなプラグイン システムが完成します。

于 2011-08-08T06:52:02.410 に答える