Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 修改的责任链_C#_Design Patterns_Chain Of Responsibility - Fatal编程技术网

C# 修改的责任链

C# 修改的责任链,c#,design-patterns,chain-of-responsibility,C#,Design Patterns,Chain Of Responsibility,我非常理解责任链模式的基本原理。但是,我想问一下,是否可以动态设置序列中的下一个接收器 其基本思想是,根据批准者的顺序,它将实例化下一个对象 下面是一个例子: 抽象基类 public abstract class ApproverCategorizer { protected ApproverCategorizer NextApprover { get; private set; } public ApproverCategorizer RegisterNextApprover

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

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

下面是一个例子:

抽象基类

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

    }

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


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

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

只需对代码进行很少的更改,这是可能的。这是所需的修改

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

并且您的
TestEntity
类将不具有
ApproverQueue
属性。

当然,可以让代码按照您描述的方式工作。但在我看来,当你这样做的时候,你不再真正有“责任链”的实施。因此,如果你的问题是“在仍然使用‘责任链’的情况下是否有可能做到这一点?”我会说答案是“不”。但当然,这是一个固执己见的答案,正是像这样的问题可能引发的类型。@PeterDuniho你为什么说你不再真正有“责任链”?责任链模式中的OP违反了什么?模式并不要求在编译时进行连接。@SriramSakthivel:坦白说,这正是我要说的。设计模式本身就是主观的,对于“设计模式的一部分”和“不是设计模式的一部分”这两个模糊阈值的位置,你和我显然有一个基本的分歧。你比我更广泛地定义了这个模式。这不是讨论此类问题的合适论坛。@PeterDuniho我的观点是形式定义不要求在编译时进行。是的,我同意这不是辩论的地方,但如果你有什么好的东西来强化你的观点,我很高兴听到。顺便说一句,我不知道为什么这个问题被投票以“基于意见”结束。OP没有问这样做是对还是错,这是主观的,问题是如何让他的代码工作。我无法理解它到底是如何“基于观点的”。@SriramSakthivel:对于我们每天在编程中使用的任何设计模式,都没有“正式定义”。正确使用,他们是流动的,适应眼前的需要,没有承诺的教条。但同时,对于模式的边界是什么以及某些更改是否会将代码推到这些边界之外,每个人都有自己的主观立场。OP提出了一个模糊的“是否可能”问题,如果将其解释为询问是否有可能做到他所说的并且仍然保持这种模式,对我来说显然是一个意见问题。实际上,我将我的初始版本修改为我想要的,令人惊讶的是,我们几乎有相同的设计。感谢各位的辩论和澄清。:)
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";
        }
    }
}