修改的责任链

时间:2015-03-17 06:02:00

标签: c# design-patterns chain-of-responsibility

我完全理解责任链模式的基础知识。但是,我想问一下是否可以动态地设置序列中的下一个接收器。

基本思想是,根据审批者的顺序,它将实例化下一个对象。

以下是示例:

抽象基类

public abstract class ApproverCategorizer
{
    protected ApproverCategorizer NextApprover { get; private set; }

    public ApproverCategorizer RegisterNextApprover(ApproverCategorizer nextApprover)
    {
        NextApprover = nextApprover;
        return nextApprover;
    }

    public abstract void ApproveAmount(TestEntity entity);

    protected bool IsLast(Queue<string> approverQueue)
    {
        return string.IsNullOrEmpty(approverQueue.Peek());
    }
}

主管审批人类

public class OfficerAApprover : ApproverCategorizer
{
    public override void ApproveAmount(TestEntity entity)
    {
        entity.ApproverQueue.Dequeue();

        if (entity.Amount <= 300)
        {
            entity.Status = "Approved";
            return;
        }

        if (!IsLast(entity.ApproverQueue) && string.IsNullOrWhiteSpace(entity.Status))
        {
            NextApprover.ApproveAmount(entity);
            return;
        }
        else
        {
            entity.Status = "Rejected";
        }

    }

}

B级军官

public class OfficerBApprover : ApproverCategorizer
{
    public override void ApproveAmount(TestEntity entity)
    {
        entity.ApproverQueue.Dequeue();

        if (entity.Amount <= 300)
        {
            entity.Status = "Approved";
            return;
        }

        if (!IsLast(entity.ApproverQueue) && string.IsNullOrWhiteSpace(entity.Status))
        {
            NextApprover.ApproveAmount(entity);
            return;
        }
        else
        {
            entity.Status = "Rejected";
        }

    }

}

审批人链类

public class ApproverChain
{
    public static TestEntity Entity { get; set; }
    public static ApproverCategorizer Approver { get; set; }

    public ApproverChain()
    {
        List<string> approverList = Entity.ApproverList.Split(',').ToList();
        Queue<string> approverQueue = new Queue<string>();

        Approver = new StartApprover();
        // Note: The code below is working, but not the desired logic.
        //Approver.RegisterNextApprover(new OfficerAApprover()).RegisterNextApprover(new OfficerBApprover());

        // Note: This code below is not working, but this is the desired logic.
        foreach (string approver in approverList)
        {
            switch (approver)
            {
                case "OfficerA":
                    Approver.RegisterNextApprover(new OfficerAApprover());
                    break;
                case "OfficerB":
                    Approver.RegisterNextApprover(new OfficerBApprover());
                    break;
            }
            approverQueue.Enqueue(approver);

        }

        Entity.ApproverQueue = approverQueue;

    }

    public string StartProcess()
    {
        Approver.ApproveAmount(Entity);
        return Entity.Status;
    }
}

商务舱

public string ProcessApproval()
{
  TestEntity entity = new TestEntity
  {
     Amount = 500,
     ApproverList = "OfficerB,OfficerA"
  };

  ApproverChain.Entity = entity;
  ApproverChain chain = new ApproverChain();
  var result = chain.StartProcess();

  return result;
}

这意味着OfficerB类将首先处理。如果失败,它将转到OfficerA类。

有没有办法将它调整到所提到的所需逻辑?如果是这样,它是如何完成的?

1 个答案:

答案 0 :(得分:3)

如果我理解正确,您需要通过运行时值配置批准者(在本例中为字符串)。

您的代码几乎没有变化,这是可能的。这是必要的修改。

public ApproverChain()
{
    List<string> approverList = Entity.ApproverList.Split(',').ToList();
    Queue<string> approverQueue = new Queue<string>();

    Approver = new StartApprover();

    ApproverCategorizer currentApprover = Approver;
    foreach (string approver in approverList)
    {
        switch (approver)
        {
            case "OfficerA":
                currentApprover = currentApprover.RegisterNextApprover(new OfficerAApprover());
                break;
            case "OfficerB":
                currentApprover = currentApprover.RegisterNextApprover(new OfficerBApprover());
                break;
        }
        approverQueue.Enqueue(approver);
    }

    Entity.ApproverQueue = approverQueue;
}

上面的代码可以正常工作。但对我来说,ApproverQueue看起来很可疑。

您似乎拥有ApproverQueue财产只是为了确定当前审批人是否是链中的最后一个审批人。您只需将NextApprover设为null即可找到它,并完全摆脱approverQueue

然后您的代码变为

public class ApproverChain
{
    public static TestEntity Entity { get; set; }
    public static ApproverCategorizer Approver { get; set; }

    public ApproverChain()
    {
        Approver = new StartApprover();

        List<string> approverList = Entity.ApproverList.Split(',').ToList();

        ApproverCategorizer currentApprover = Approver;
        foreach (string approver in approverList)
        {
            switch (approver)
            {
                case "OfficerA":
                    currentApprover = currentApprover.RegisterNextApprover(new OfficerAApprover());
                    break;
                case "OfficerB":
                    currentApprover = currentApprover.RegisterNextApprover(new OfficerBApprover());
                    break;
            }
        }
    }

    public string StartProcess()
    {
        Approver.ApproveAmount(Entity);
        return Entity.Status;
    }
}

public abstract class ApproverCategorizer
{
    protected ApproverCategorizer NextApprover { get; private set; }

    public ApproverCategorizer RegisterNextApprover(ApproverCategorizer nextApprover)
    {
        NextApprover = nextApprover;
        return nextApprover;
    }

    public abstract void ApproveAmount(TestEntity entity);

    protected bool IsLast()
    {
        return NextApprover == null;
    }
}

public class OfficerAApprover : ApproverCategorizer
{
    public override void ApproveAmount(TestEntity entity)
    {
        if (entity.Amount <= 300)
        {
            entity.Status = "Approved";
            return;
        }

        if (!IsLast() && string.IsNullOrWhiteSpace(entity.Status))
        {
            NextApprover.ApproveAmount(entity);
            return;
        }
        else
        {
            entity.Status = "Rejected";
        }
    }
}

您的TestEntity课程不会有ApproverQueue属性。