书接上文,状态模式完美解决了多判断分支分支问题,符合了我人生信条的第1、第三条。今天来探讨一下状态模式异父异母的亲兄弟职责链模式,它们都有殊途同归之妙,实际开发中可根据口味,自行选用。html
今天的故事背景就放在咱们平时 申请加薪、请假等活动中,咱们都知道,随着咱们申请内容的不一样,审批人员的等级也不一样。咱们就先用最简单的代码模拟一下git
RequestType枚举,规范咱们申请的类型app
/// <summary> /// 请求类型 /// </summary> public enum RequestType { /// <summary> /// 请假 /// </summary> Leave, /// <summary> /// 加薪 /// </summary> PayRise }
Requset类,简单描述申请内容ide
/// <summary> /// 请求 /// </summary> public class Requset { /// <summary> /// 请求类型 /// </summary> public RequestType Type { get; set; } /// <summary> /// 请求数量 /// </summary> public int Number { get; set; } /// <summary> /// 请求说明 /// </summary> public string Content { get { switch (Type) { case RequestType.Leave: return $"请假{Number}天"; case RequestType.PayRise: return $"加薪{Number}元"; default: return "未知"; } } } }
ManagerType枚举,定义不一样的审批人员类型优化
/// <summary> /// 管理者类型 /// </summary> public enum ManagerType { PM, CTO, CEO }
Manager类,审批人员,处理咱们的请求code
public class Manager { private readonly ManagerType _managerType; public Manager(ManagerType managerType) { _managerType = managerType; } /// <summary> /// 处理请求 /// </summary> public void Process(Requset requset) { if (_managerType == ManagerType.PM) { if (requset.Type == RequestType.Leave && requset.Number <= 2) { Console.WriteLine($"项目经理 已批准 你的 {requset.Content} 申请"); } else { Console.WriteLine($"项目经理 无权批准 你的 {requset.Content} 申请"); } } else if (_managerType == ManagerType.CTO) { if (requset.Type == RequestType.Leave) { if (requset.Number <= 5) { Console.WriteLine($"CTO 已批准 你的 {requset.Content} 申请"); } else { Console.WriteLine($"CTO 无权批准 你的 {requset.Content} 申请"); } } else { if (requset.Number <= 500) { Console.WriteLine($"CTO 已批准 你的 {requset.Content} 申请"); } else { Console.WriteLine($"CTO 无权批准 你的 {requset.Content} 申请"); } } } else if (_managerType == ManagerType.CEO) { if (requset.Type == RequestType.Leave) { Console.WriteLine($"CEO 已批准 你的 {requset.Content} 申请"); } else { if (requset.Number <= 1000) { Console.WriteLine($"CEO 已批准 你的 {requset.Content} 申请"); } else { Console.WriteLine($"CEO对你的 {requset.Content} 申请 说:“小子,你有点飘啊!”"); } } } } }
客户端htm
internal class Program { private static void Main(string[] args) { //建立领导 var pm = new Manager(ManagerType.PM); var cto = new Manager(ManagerType.CTO); var ceo = new Manager(ManagerType.CEO); //建立 请假请求 var request1 = new Requset { Type = RequestType.Leave, Number = 5 }; pm.Process(request1); cto.Process(request1); ceo.Process(request1); Console.WriteLine("\n"); //建立 加薪请求 var request2 = new Requset { Type = RequestType.PayRise, Number = 2000 }; pm.Process(request2); cto.Process(request2); ceo.Process(request2); Console.WriteLine("\nHappy Ending~"); Console.ReadLine(); } }
结果展现:对象
项目经理 无权批准 你的 请假5天 申请 CTO 已批准 你的 请假5天 申请 CEO 已批准 你的 请假5天 申请 项目经理 无权批准 你的 加薪2000元 申请 CTO 无权批准 你的 加薪2000元 申请 CEO对你的 加薪2000元 申请 说:“小子,你有点飘啊!”
咱们Code Review后,就会发现Manager.Process()又丑又长呀,一样是咱们选侍女时出现的三个问题:方法长,分支多,难维护。blog
那咱们怎么使用职责链模式来解决呢?咱们先来了解一下它...继承
敲黑板·划重点
定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一个链,并沿着这条链传递请求,知道有一个对象处理请求为止。
好处: 接收者和发送者都没有对方的明确信息,且链中的对象本身也并不知道链的结构。结果是职责链可简化对象的相互链接,它们仅需保持一个指向其后继者的引用,而不须要保持它全部的候选接受者的引用。【下降耦合度】
注意: 一个请求极有可能到了链的末端都得不处处理,或者由于没有正确配置而得不处处理,须要考虑全面!
在下面代码优化中来深化对定义、好处的理解吧
Manager抽象类,不一样权限审批人员的基类,能够设置下一级审批人员,造成一条职责链
public abstract class Manager { protected readonly ManagerType _managerType; /// <summary> /// 下一个处理者 /// </summary> protected Manager Successor { get; private set; } public Manager(ManagerType managerType) { _managerType = managerType; } /// <summary> /// 设置下一个处理者 /// </summary> /// <param name="manager"></param> public void SetSuccessor(Manager manager) { Successor = manager; } /// <summary> /// 处理请求 /// </summary> /// <param name="requset"></param> public abstract void Process(Requset requset); }
PM、CTO、CEO类,具体的审批人,实现处理方法Process()
public class PM : Manager { public PM(ManagerType managerType) : base(managerType) { } public override void Process(Requset requset) { if (requset.Type == RequestType.Leave && requset.Number <= 2) { Console.WriteLine($"项目经理 已批准 你的 {requset.Content} 申请"); return; } if (Successor != null) { //交由下一级处理 Successor.Process(requset); } } } public class CTO : Manager { public CTO(ManagerType managerType) : base(managerType) { } public override void Process(Requset requset) { if (requset.Type == RequestType.Leave && requset.Number <= 5) { Console.WriteLine($"CTO 已批准 你的 {requset.Content} 申请"); return; } if (requset.Type == RequestType.PayRise && requset.Number <= 500) { Console.WriteLine($"CTO 已批准 你的 {requset.Content} 申请"); return; } if (Successor != null) { //交由下一级处理 Successor.Process(requset); } } } public class CEO : Manager { public CEO(ManagerType managerType) : base(managerType) { } public override void Process(Requset requset) { if (requset.Type == RequestType.Leave && requset.Number <= 15) { Console.WriteLine($"CEO 已批准 你的 {requset.Content} 申请"); return; } if (requset.Type == RequestType.PayRise && requset.Number <= 1000) { Console.WriteLine($"CEO 已批准 你的 {requset.Content} 申请"); return; } Console.WriteLine($"CEO对你的 {requset.Content} 申请 说:“小子,你有点飘啊!”"); } }
客户端代码
internal class Program { private static void Main(string[] args) { //建立领导 var pm = new PM(ManagerType.PM); var cto = new CTO(ManagerType.CTO); var ceo = new CEO(ManagerType.CEO); //设置下一级处理者 pm.SetSuccessor(cto); cto.SetSuccessor(ceo); //建立 请假请求 var request1 = new Requset { Type = RequestType.Leave, Number = 5 }; pm.Process(request1); Console.WriteLine("\n"); //建立 加薪请求 var request2 = new Requset { Type = RequestType.PayRise, Number = 2000 }; pm.Process(request2); Console.WriteLine("\nHappy Ending~"); Console.ReadLine(); } }
结果展现:
CTO 已批准 你的 请假5天 申请 CEO对你的 加薪2000元 申请 说:“小子,你有点飘啊!”
这样咱们也消除上面三个问题。当需求须要人事加入审批流程时,只须要增长一个继承Manager的人事类;当需求要求不须要CTO审批,直接由PM转到CEO时,咱们只用修改PM的SetSuccessor(),这也体现了职责链的灵活性。
示例代码地址: https://gitee.com/sayook/DesignMode/tree/master/ChainOfResponsibility