首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >修正责任链

修正责任链
EN

Stack Overflow用户
提问于 2015-03-17 06:02:00
回答 1查看 862关注 0票数 1

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

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

下面是一个例子:

抽象基类

代码语言:javascript
复制
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());
    }
}

高级审批人级

代码语言:javascript
复制
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级

代码语言:javascript
复制
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";
        }

    }

}

认可链类

代码语言:javascript
复制
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;
    }
}

商务类

代码语言:javascript
复制
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类。

是否有一种方法可以将其调整为所需的逻辑?如果是的话,是如何做到的?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-17 07:11:53

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

如果您的代码很少更改,这是可能的。这是所需的修改。

代码语言:javascript
复制
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来找到它。

那么您的代码就变成了

代码语言:javascript
复制
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属性。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29092296

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档