1

すべて同様の動作をするオブジェクトの階層があります。動作を POCO 定義から分離したいと考えています。動作はオブジェクトをさまざまな状態に移動することを表しているため、これは状態パターンの仕事のように思えます。ただし、各オブジェクトの動作がわずかに異なる可能性があるため、関数ごとに 1 つの定義があるほど単純ではありません。

たとえば、抽象基本クラスに基づいて、次のクラスがあるとします。

public abstract BaseClass
{
    public int Property1 { get; set; }
    public int Property2 { get; set; }
}

public Class1 : BaseClass
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
}

public Class2 : BaseClass
{
    public string PropertyC { get; set; }
    public string PropertyD { get; set; }
}

階層は、さまざまなタイプのオブジェクトを表します。また、オブジェクトはすべて同じ基本的なワークフロー (送信済み、承認済み、実行済み、クローズ済み) に従っているとしましょう。

現在、各関数の動作も階層的です。つまり、Class1 で関数 Approve() を呼び出すことは、BaseClass から継承された動作を呼び出すことと同じである必要がありますが、Class2 は Approve() 関数をオーバーライドします。これは、そのタイプが異なる承認に従うためです。処理する。

State Pattern をこれらのオブジェクトに適用しようとして迷っています。関数をオブジェクト自体に配置し、そのように継承することを選択できます。これは正常に機能しますが、POCO 設計が壊れます。オブジェクトの種類ごとに switch ステートメントを使用して Approve() 関数を実装することもできますが、それでは多態的な設計ができなくなります。

状態パターンを多層ポリモーフィック オブジェクト定義に適用し、設計原則との一貫性を維持するにはどうすればよいですか。

更新:明確にさせてください。オブジェクトに作用する以外のことを行う関数はPOCOに属していないと思います。例: 承認機能は、オブジェクトの状態を変更するだけでなく、電子メールを送信し、他のシステムでイベントをトリガーします。多分それは私だけです。

4

3 に答える 3

1

オブジェクトにメソッドを配置しても、「POCOデザイン」(標準の「POCOデザイン」はありません)が壊れることはありません。POCOは、単純なオブジェクトと、より大きなフレームワークを使用するより複雑なオブジェクトや重いオブジェクトとを対比するために使用される用語です。 。この用語は通常、単純なCLRタイプ(したがって「PlainOld CLR Objects」の頭字語)であるオブジェクトと、共通の実装固有の基本タイプから継承するオブジェクトを区別するためにORMで使用されます。同様に、POCOを使用して、型自体がそれを使用しているORMまたはライブラリに直接接続していないことを示すこともできるため、他の人と簡単に使用できます。

つまり、タイプのメソッドで説明したのと同じように実行します。

于 2011-10-27T12:48:44.180 に答える
1

関数をオブジェクト自体に配置し、そのように継承することを選択できます。これは正常に機能しますが、POCO 設計が壊れます

したがって、POCO の設計が崩れることはないという点で、ここにいる全員に同意します。たとえば、次のようになります。

  public class BaseClass
  {
     public int Property1 { get; set; }
     public int Property2 { get; set; }
     public virtual bool Submitted() { return (Property1 != 0); }
     public virtual bool Approved() { return (Property2 != 0); }
     // ...
  }

  public class Class1 : BaseClass
  {
     public string PropertyA { get; set; }
     public string PropertyB { get; set; }
     public override bool Submitted() 
     { return !String.IsNullOrEmpty(PropertyA); }
     public override bool Approved() 
     // Or do specific Class1 Approval actions...
     { return !String.IsNullOrEmpty(PropertyB); }
     // ...
  }

  public class Class2 : BaseClass
  {
     public string PropertyC { get; set; }
     public string PropertyD { get; set; }
     public override bool Submitted()
     { return !String.IsNullOrEmpty(PropertyC); }
     public override bool Approved()
     { return !String.IsNullOrEmpty(PropertyD); }
     // ...
  }

  public abstract class WorkflowState<PocoType> 
     where PocoType : BaseClass
  {
     private WorkflowManager<PocoType> _workflowManger;
     private PocoType _pocoObject;

     public WorkflowManager<PocoType> Workflow
     {
        get { return _workflowManger; }
        set { _workflowManger = value; }
     }

     public PocoType PocoObject
     {
        get { return _pocoObject; }
        set { _pocoObject = value; }
     }

     public abstract void Submitted();
     public abstract void Approved();
     // ...
  }

  public class InitialState<PocoType> : 
     WorkflowState<PocoType> where PocoType : BaseClass
  {
     public InitialState(PocoType pocoObject)
     {
        base.PocoObject = pocoObject;
     }

     public override void Submitted()
     {
        if (PocoObject.Submitted())
        {
           // move to approved state if submitted is ok for the poco
           // definition
           Workflow.State = new ApprovedState<PocoType>(this);
        }
     }

     public override void Approved()
     {
        // Not supported state
        throw new InvalidOperationException();
     }

     // ...
  }

  public class ApprovedState<PocoType> :
     WorkflowState<PocoType> where PocoType : BaseClass
  {
     public ApprovedState(WorkflowState<PocoType> state)
     {
        base.PocoObject = state.PocoObject;
        base.Workflow = state.Workflow;
     }

     public override void Submitted()
     {
        // Not supported state
        throw new InvalidOperationException();
     }

     public override void Approved()
     {
        if (PocoObject.Approved())
        {
           // next state ...
           //Workflow.State = ...
           //Send emails
           //Do approval items
        }
     }
  }

  public class WorkflowManager<PocoType> where PocoType : BaseClass
  {
     WorkflowState<PocoType> _state;

     public WorkflowManager(PocoType pocoObject)
     {
        this._state = new InitialState<PocoType>(pocoObject);
        this._state.Workflow = this;
     }

     public WorkflowState<PocoType> State
     {
        get { return _state; }
        set { _state = value; }
     }

     public void RunWorkflow()
     {
        State.Submitted();
        State.Approved();
     }
  }

実行のいくつかの異なる例は、次のようになります。

Class1 test = new Class1();
test.PropertyA = "hello";
WorkflowManager<Class1> work_flow_man = new WorkflowManager<Class1>(test);
work_flow_man.RunWorkflow();

Class2 test2 = new Class2();
test2.PropertyC = "cool";
test2.PropertyD = "dude";
WorkflowManager<Class2> work_flow_man2 = new WorkflowManager<Class2>(test2);
work_flow_man2.RunWorkflow();
于 2011-10-27T14:10:34.433 に答える
0

状態間の遷移を定義するコードを集中化する方法についての見通しを示すために、私はかなり前に状態パターンについて頭を悩ませました。当時、ジェネリックはかなり新しいものだったので、それについては少し重くなっています。いずれにせよ、状態パターンを実装する方法について別の視点が得られるかもしれません。

于 2011-10-27T12:42:16.833 に答える