我非常了解责任链模式的基础知识。但是,我想问一下是否可以动态设置序列中的下一个接收者。
基本思想是根据批准者的先后顺序,实例化下一个对象。
示例如下:
抽象基类
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
类。
有没有办法将其调整为所提到的所需逻辑?如果是这样,它是如何完成的?
如果我理解正确,您需要通过运行时值(在本例中为字符串)配置您的批准者。
只需对您的代码进行很少的更改,这是可能的。这是所需的修改。
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
属性。
我是一名优秀的程序员,十分优秀!