修改后的责任链
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";
}
}
}
而你的TestEntity
class不会有ApproverQueue
属性。
我非常了解责任链模式的基础知识。但是,我想问一下是否可以动态设置序列中的下一个接收者。
基本思路是根据审批人的先后顺序,实例化下一个对象。
示例如下:
抽象基础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";
}
}
}
而你的TestEntity
class不会有ApproverQueue
属性。