经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式-行为型-职责链模式
来源:cnblogs  作者:酷学大叔  时间:2019/10/8 9:27:56  对本文有异议

职责链模式(Chain of Responsibility):

  在现实生活中,常常会出现这样的事例:一个请求需要多个对象处理,但每个对象的处理条件或权限不同。如公司员工报销差旅费,可审批的领导有部分负责人、副总经理、总经理等,但每个领导能审批的金额是不同的,不同的金额需要找相应的领导审批,也就是说要报销必须先搞清楚需要谁来审批。职责链模式就是为了解决这样的问题产生的。

  职责链模式,又叫责任链模式。是为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一个对象记住其下一个对象的引用而连成一条链。当发生请求时,可将请求沿着这条链传递,直到有对象处理它为止。

职责链模式的角色:

  

  1)抽象处理者(Handler):声明了所有具体处理者的通用接口 该接口通常仅包含单个方法用于请求处理 但有时其还会包含一个设置链上下个处理者的方法

  2)具体处理者(ConcreteHandler):包含处理请求的实际代码 每个处理者接收到请求后 都必须决定是否进行处理 以及是否沿着链传递请求处理者通常是独立且不可变的 需要通过构造函数一次性地获得所有必要地数据

  3)请求信息(Request):定义请求的信息。

  4)客户端(Client):可根据程序逻辑一次性或者动态地生成链值得注意的是,请求可发送给链上的任意一个处理者而非必须是第一个处理者

责任链的实现:(以请假为例) 

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 //构建各个领导人
  6. 6 Leader director = new Director("张三");//主任
  7. 7 Leader manager = new Manager("李四");//经理
  8. 8 Leader generalManager = new GeneralManager("王五");//总经理
  9. 9 //设置各个责任链上的关系
  10. 10 director.setNextLeader(manager);//主任的下一个审批人为经理
  11. 11 manager.setNextLeader(generalManager);//经理的下一个审批人为总经理
  12. 12
  13. 13 //开始请假
  14. 14 LeaveRequest request = new LeaveRequest("小明", 5, "旅游");
  15. 15 director.HandleRequest(request);//小明提交了请假申请给主任
  16. 16 }
  17. 17 }
  18. 18
  19. 19 /// <summary>
  20. 20 /// 请假的信息
  21. 21 /// </summary>
  22. 22 public class LeaveRequest
  23. 23 {
  24. 24 public string EmplName { get; set; }
  25. 25 public int LeaveDays { get; set; }
  26. 26 public string Reason { get; set; }
  27. 27
  28. 28 public LeaveRequest(string emplName, int leaveDays, string reason)
  29. 29 {
  30. 30 this.EmplName = emplName;
  31. 31 this.LeaveDays = leaveDays;
  32. 32 this.Reason = reason;
  33. 33 }
  34. 34 }
  35. 35
  36. 36 /// <summary>
  37. 37 /// 管理责任链上的对象处理的抽象类
  38. 38 /// </summary>
  39. 39 public abstract class Leader
  40. 40 {
  41. 41 protected string name;
  42. 42 protected Leader nextLeader;//下一个继承者
  43. 43
  44. 44 public Leader(string name)
  45. 45 {
  46. 46 this.name = name;
  47. 47 }
  48. 48
  49. 49 /// <summary>
  50. 50 /// 设置责任链上的下一个继承者
  51. 51 /// </summary>
  52. 52 /// <param name="leader"></param>
  53. 53 public void setNextLeader(Leader leader)
  54. 54 {
  55. 55 this.nextLeader = leader;
  56. 56 }
  57. 57
  58. 58 /// <summary>
  59. 59 /// 处理请求的抽象方法
  60. 60 /// </summary>
  61. 61 /// <param name="leader"></param>
  62. 62 public abstract void HandleRequest(LeaveRequest leader);
  63. 63 }
  64. 64
  65. 65 /// <summary>
  66. 66 /// 主任: 处理小于等于3天的假期
  67. 67 /// </summary>
  68. 68 public class Director : Leader
  69. 69 {
  70. 70 public Director(string name)
  71. 71 : base(name)
  72. 72 {
  73. 73 }
  74. 74
  75. 75 /// <summary>
  76. 76 /// 责任链上对象对请求的具体处理
  77. 77 /// </summary>
  78. 78 /// <param name="leader"></param>
  79. 79 public override void HandleRequest(LeaveRequest leader)
  80. 80 {
  81. 81 if (leader.LeaveDays <= 3)
  82. 82 {
  83. 83 Console.WriteLine($"请假人:{leader.EmplName},天数{leader.LeaveDays},理由:{leader.Reason}");
  84. 84 Console.WriteLine($"审批人:{this.name } 主任,审批通过!");
  85. 85 }
  86. 86 else
  87. 87 {
  88. 88 if (this.nextLeader != null)
  89. 89 {
  90. 90 this.nextLeader.HandleRequest(leader);
  91. 91 }
  92. 92 }
  93. 93 }
  94. 94 }
  95. 95
  96. 96 /// <summary>
  97. 97 /// 经理: 处理大于3天,小于等于10天的假期
  98. 98 /// </summary>
  99. 99 public class Manager : Leader
  100. 100 {
  101. 101 public Manager(string name)
  102. 102 : base(name)
  103. 103 {
  104. 104 }
  105. 105
  106. 106 /// <summary>
  107. 107 /// 责任链上对象对请求的具体处理
  108. 108 /// </summary>
  109. 109 /// <param name="leader"></param>
  110. 110 public override void HandleRequest(LeaveRequest leader)
  111. 111 {
  112. 112 if (leader.LeaveDays > 3 && leader.LeaveDays <= 10)
  113. 113 {
  114. 114 Console.WriteLine($"请假人:{leader.EmplName},天数{leader.LeaveDays},理由:{leader.Reason}");
  115. 115 Console.WriteLine($"审批人:{this.name } 经理,审批通过!");
  116. 116 }
  117. 117 else
  118. 118 {
  119. 119 if (this.nextLeader != null)
  120. 120 {
  121. 121 this.nextLeader.HandleRequest(leader);
  122. 122 }
  123. 123 }
  124. 124 }
  125. 125 }
  126. 126
  127. 127 /// <summary>
  128. 128 /// 总经理: 处理大于10天,小于等于30天的请假信息
  129. 129 /// </summary>
  130. 130 public class GeneralManager : Leader
  131. 131 {
  132. 132 public GeneralManager(string name)
  133. 133 : base(name)
  134. 134 {
  135. 135 }
  136. 136
  137. 137 /// <summary>
  138. 138 /// 责任链上对象对请求的具体处理
  139. 139 /// </summary>
  140. 140 /// <param name="leader"></param>
  141. 141 public override void HandleRequest(LeaveRequest leader)
  142. 142 {
  143. 143 if (leader.LeaveDays > 10 && leader.LeaveDays <= 30)
  144. 144 {
  145. 145 Console.WriteLine($"请假人:{leader.EmplName},天数{leader.LeaveDays},理由:{leader.Reason}");
  146. 146 Console.WriteLine($"审批人:{this.name } 总经理,审批通过!");
  147. 147 }
  148. 148 else
  149. 149 {
  150. 150 if (this.nextLeader != null)
  151. 151 {
  152. 152 this.nextLeader.HandleRequest(leader);
  153. 153 }
  154. 154 else
  155. 155 {
  156. 156 Console.WriteLine($"你疯了!!!");
  157. 157 }
  158. 158 }
  159. 159 }
  160. 160 }

  从实现上可以看出,每个领导只处理自己能力范围内的事情,不是自己的坚决不处理;同时职责链是动态构建的,下一个处理者由调用者自己设置;缺少处理对象可以直接添加,符合开闭原则。

职责链的优缺点:

  优点:

    1)请求者和接收者松耦合。在职责链模式中,请求者并不知道接收者是谁,也不知道具体如何处理,请求者只是负责向职责链发送请求就可以了。而每个职责对象也不用管请求者或者是其他的职责对象,只负责处理自己的部分,其他的就交给其他的职责对象去处理。也就是说,请求者和接受者是完全解耦的。

    2)动态组合职责。职责链模式会把功能处理分散到单独的职责对象中,然后再使用的时候,可以动态组合职责形成职责链,从而可以灵活地给对象分配职责,也可以灵活地实现和改变对象的职责。

    3)减少代码中的if..else..判断,优化代码。

  缺点:

    1)产生很多细粒度对象。职责链模式会把功能处理分散到单独的职责对象中,也就是每个职责对象只处理一个方面的功能,要把整个业务处理完,需要很多职责对象的组合,这样会产生大量的细粒度职责对象。

    2)不一定能被处理。职责链模式的每个职责对象只负责自己处理的那一部分,因此可能会出现某个请求把整个链传递完了都没有职责对象处理它。这就需要使用职责链模式的时候,需要提供默认的处理,并且注意构造的链的有效性。

    3)职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

职责链的应用场景:

  1)有多个对象可以处理一个请求,哪个对象处理该请求由运行时刻自动确定。

  2)可动态指定一组对象处理请求,或添加新的处理者。

  3)在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。

参考:https://www.cnblogs.com/cxxjohnson/p/6403849.html

原文链接:http://www.cnblogs.com/az4215/p/11621948.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号