我正在为工作流程层次结构编写存储解决方案。
为了简化图片,我有两种类型的对象,一个工作流和一个WorkflowStep。
即使WorkflowStep在工作流下层次结构,工作流也不会聚合WorkflowStep,因为我们将这些对象视为数据容器。
所以这给我留下了以下几个类:
public class Workflow : Node {
public string UID;
public string parentID;
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
}
public class WorkflowEngine {
public void Store(Workflow wf) {
}
public void Store(WorkflowStep wfs) {
}
}
不在工作流内聚合WorkflowStep的原因(即使逻辑上适合)是这些对象纯粹被视为数据容器,以后它们可能会受到更改,我们希望保持这些对象的存储与对象本身。
另一种选择当然是做这样的事情:
public class Workflow : Node {
public List<WorkflowStep> steps;
public string UID;
public string parentUID;
public void Store() { }
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
public void Store() { }
}
两种方法的优点和缺点是什么?有没有关于这两种设计的文献?
答案 0 :(得分:1)
即使Workflow
和WorkflowStep
都是数据容器,但将这些保留在分层度量之外并不能解决您的解耦问题。
将WorkflowStep
保留在Workflow
的层次结构上更合乎逻辑,并且在这种情况下必须引入IoC
。
IoC
的美丽之处在于更改WorkflowStep
类Workflow
中的列表的定义将是透明的,您只会考虑在IoC
上注册您的类型{1}}容器。
让我举一个使用Ninject
IoC
容器框架的示例。
定义接口并相应地实现数据容器:
public interface IWorkflow {
string UID { get; set; }
string parentID { get; set; }
IList<IWorkflowStep> Steps { get; set; }
}
public interface IWorkflowStep {
string UID { get; set; }
string parentID { get; set; }
}
public class Workflow : IWorkflow, Node {
public string UID { get; set; };
public string parentID { get; set; };
public IList<IWorkflowStep> Steps { get; set; }
}
public class WorkflowStep : IWorkflowStep, Node {
public string UID { get; set; };
public string parentID { get; set; };
}
现在,Ninject模块是:
public class WorkflowModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IWorkflow>().To<Workflow>();
Bind<IWorkflowStep>().To<WorkflowStep>();
Bind<IList>().To<List>();
}
#endregion
}
这是将接口与具体类绑定的单一位置。在世界其他地方,你只需要一个定义接口的实例。
要解析您的类型,您需要通过加载已定义的模块来创建一个Kernel
类型的Ninject IKernel
和StandardKernel
的具体实现
这就像是,
var kernel = new StandardKernel(new WorkflowModule());
现在,您所要做的就是解决所需的界面,例如:
IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();
这里的美妙之处在于,您无需担心具体实施,而且您的系统内部紧密耦合。它只是你要处理和休息的界面是你IoC
容器实现的担忧。
您更担心要更改的WorkflowStep
的实施,而不是与Workflow
的耦合。我想,这是IoC
发挥作用的地方。
请注意,您可以使用任何IoC
容器框架,例如 Unity , Spring.NET , StructureMap 等等我使用了Ninject,因为我很满意。