修改后的责任链

Modified Chain Of Responsibility

我非常了解责任链模式的基础知识。但是,我想问一下是否可以动态设置序列中的下一个接收者。

基本思路是根据审批人的先后顺序,实例化下一个对象。

示例如下:

抽象基础Class

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());
    }
}

审批人class

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 Class

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";
        }

    }

}

审批链Class

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;
    }
}

商业Class

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 class 将首先处理。如果失败,它将转到 OfficerA class.

有没有办法将其调整为所提到的所需逻辑?如果有,是怎么做到的?

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

只需对您的代码进行很少的更改,就可以实现。这是所需的修改。

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";
        }
    }
}

而你的TestEntityclass不会有ApproverQueue属性。