多态对象的状态设计模式
本文关键字:设计模式 状态 对象 多态 | 更新日期: 2023-09-27 18:12:28
我有一个具有相似行为的对象层次结构。我想将行为与POCO定义分开。由于行为表示将对象移动到各种状态,因此在我看来,这像是State Pattern的工作。但是,这并不像每个函数都有一个定义那么简单,因为每个对象的行为可能略有不同。
例如,假设我有以下基于抽象基类的类: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()函数,因为该类型遵循不同的审批过程。
我在尝试将状态模式应用于这些对象时迷失了方向。我可以选择将函数放在对象本身上并以这种方式继承它们,这很好,但它破坏了POCO设计。我还可以为每个对象类型实现带有switch语句的Approve()函数,但这会破坏我的多态设计。
如何将状态模式应用于多层多态对象定义并保持与设计原则一致。
Update:让我澄清一下,我认为除了作用于对象之外做其他事情的函数不属于POCO。例如:Approve函数将在其他系统中发送电子邮件和触发事件,而不仅仅是修改对象的状态。
我可以选择将函数放在对象本身上并以这种方式继承它们,这很好,但它破坏了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();
将方法放在对象上并不会破坏"POCO设计"(没有标准的"POCO设计"),因为POCO只是一个术语,用于将简单的对象与更复杂或重量级的对象进行对比,这些对象将使用更大的框架。该术语通常与ORM一起使用,用于区分简单CLR类型的对象(因此称为"普通旧CLR对象"的缩写)和从特定于实现的公共基类型继承的对象。类似地,POCO也可以用来指示类型本身与使用它的ORM或库没有直接连接,因此可以很容易地与其他人一起使用。
所以,简而言之,就像你在类型上描述的方法那样做。
为了让您了解如何集中定义状态之间转换的代码,我很久以前就开始研究状态模式了。在那个时候,泛型还是很新的东西,所以它有点重。无论哪种方式,它都可以为您提供关于如何实现状态模式的另一种视角。