0

我正在为工作流层次结构编写存储解决方案。

为了简化图片,我有 2 种类型的对象,一个 Workflow 和一个 WorkflowStep。

尽管 WorkflowStep 分层地位于 Workflow 之下,但 Workflow 不会聚合 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) {
    }
}

不在 Workflow 中聚合 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() { }
}

两种方法的优缺点是什么?有没有关于这两种设计的文献?

4

1 回答 1

1

尽管WorkflowWorkflowStep都是数据容器,但将这些放在分层措施之外并不能解决您的解耦问题。

在这种情况下,保持WorkflowStep层次结构Workflow并与必须引入的解耦相处更合乎逻辑。IoC

美妙之处IoC在于,更改类WorkflowStep中列表的定义Workflow将是透明的,您只会考虑在IoC容器上注册您的类型。

让我举一个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来创建一个IKernel类型和具体实现的Ninject 。StandardKernel

这就像,

var kernel = new StandardKernel(new WorkflowModule());

现在,您所要做的就是解决您想要的界面,例如:

IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();

这里的美妙之处在于,您无需担心您的具体实现,并且它在您的系统中非常紧密地耦合。它只是您将要处理的接口,其余的是您的IoC容器实现的担忧。

由于您更担心WorkflowStep要更改的实现而不是与Workflow. 我想,这就是IoC玩的地方。

请注意,您可以使用任何IoC容器框架,如UnitySpring.NETStructureMap等。我使用 Ninject 是因为我对它很熟悉。

于 2011-10-24T10:24:37.533 回答