具有多态对象的状态设计模式

问题描述 投票:1回答:3

我有一个对象的层次结构,它们都具有相似的行为。我想将行为与POCO定义分开。由于行为代表将对象移动到各种状态,因此在我看来,这就像完成状态模式的工作。但是,这并不像为每个函数定义一个单一的对象那样简单,因为每个对象的行为可能略有不同。

例如,假设我有以下基于抽象基类的类:

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()函数,因为该类型遵循a不同的批准过程。

我迷上了尝试将状态模式应用于这些对象的过程。我可以选择将函数放在对象本身上,并以这种方式继承它们,虽然效果很好,但它破坏了POCO设计。我还可以通过每种对象类型的switch语句实现Approve()函数,但这会破坏我的多态设计。

如何将状态模式应用于多层多态对象定义并与设计原则保持一致。

Update:让我澄清一下,我认为除了对对象起作用以外,执行其他操作的函数也不属于POCO。例如:“批准”功能将在其他系统中发送电子邮件和触发事件,而不仅仅是修改对象的状态。也许就是我。

c# design-patterns .net-4.0 polymorphism state-pattern
3个回答
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();

1
投票

在对象上放置方法不会破坏“ POCO设计”(没有标准的“ POCO设计”),因为POCO只是一个术语,用于将像您这样的简单对象与将要使用的更复杂或更重的对象进行对比更大的框架。该术语通常与ORM一起使用,以区分简单CLR类型的对象(因此简称为“ Plain Old CLR Objects”),这些对象是从常见的实现特定基本类型继承的。同样,POCO也可以用来指示类型本身与使用它的ORM或库没有直接连接,因此可以很容易地与其他人一起使用。

因此,简而言之,就像您对类型的方法所描述的那样进行。


0
投票

仅向您提供一个透视图,说明如何集中定义状态之间转换的代码I cracked my brain a long time ago on the state pattern。当时,泛型还很新,因此它有点繁重。无论哪种方式,它都可以为您提供关于如何实现状态模式的另一种视角。

© www.soinside.com 2019 - 2024. All rights reserved.