[关闭]
@Tyhj 2019-02-14T11:42:28.000000Z 字数 2671 阅读 826

责任链模式

设计模式


定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

使用场景

  • 多个对象可以处理同一请求,但具体由那个对象处理则在运行时动态决定
  • 在请求处理者不确定的情况下向多个对象中的一个提交一个请求
  • 需要动态的指定一组对象处理请求

理解

感觉很简单,不管下面如何去实现,只要构建了一条链,把请求按照这条链传递下去,避免请求者和接收者之间的耦合,就是责任链模式

举个栗子

网上最多的例子,解决审批权限问题;过年我要请假在家里多玩几天,请一个月假,项目经理说他最多审批2天的,多了找主管,主管说,一个月太过分了,他只能审批5天以内的,一个月要找老板,找老板,老板说小问题,准了;

用户接口

  1. public interface User {
  2. /**
  3. * 请假审批
  4. */
  5. void approval();
  6. }

请假类

  1. public class Vacation {
  2. /**
  3. * 请假天数
  4. */
  5. int days;
  6. public Vacation(int days) {
  7. this.days = days;
  8. }
  9. }

去请假

  1. public void leave(Vacation vacation) {
  2. User boss=new Boss();
  3. User director=new Director();
  4. User manager=new Manager();
  5. if (vacation.days <= 2) {
  6. manager.approval();
  7. } else if (vacation.days <= 5) {
  8. director.approval();
  9. } else {
  10. boss.approval();
  11. }
  12. }

这个写法肯定是有问题的吧,看到if-else就知道是不符合开闭原则,修改容易引起错误;而且代码臃肿;具体的处理逻辑我们放到了这个场景类里面也不是很合理,应该放到各个用户中处理

重构

修改用户接口

  1. public abstract class User {
  2. /**
  3. * 上一级领导
  4. */
  5. protected User nextUser;
  6. /**
  7. * 处理请假
  8. *
  9. * @param vacation 请假
  10. */
  11. public final void handleRequest(Vacation vacation) {
  12. if (vacation.days <= limit()) {
  13. approval();
  14. } else {
  15. if (null != nextUser) {
  16. nextUser.handleRequest(vacation);
  17. }
  18. }
  19. }
  20. /**
  21. * 能审批的天数
  22. *
  23. * @return 天数
  24. */
  25. public abstract int limit();
  26. /**
  27. * 请假审批
  28. */
  29. public abstract void approval();
  30. }

主管实现类,其他差不多

  1. public class Director extends User {
  2. @Override
  3. public int limit() {
  4. return 5;
  5. }
  6. @Override
  7. public void approval() {
  8. System.out.println("主管审批通过");
  9. }
  10. }

去请假

  1. public void leave(Vacation vacation) {
  2. User boss=new Boss();
  3. User director=new Director();
  4. User manager=new Manager();
  5. manager.nextUser=director;
  6. director.nextUser=boss;
  7. manager.handleRequest(vacation);
  8. }

1.责任链模式与 if-else 相比,耦合性要低一些,因为它将条件判定分散到各个处理类中,并且这些处理类的优先处理顺序可以随意的设定,并且如果想要添加新的 handler 类也是十分简单的,这符合开放闭合原则。
2.责任链模式感觉也更灵活,思路更清晰一些

功能链

标准的责任链模式,一个请求只能被一个节点处理,感觉其实应用的场景不是很多;一个请求被多个节点处理的场景要多一个,其实做法是差不多的;比如实现一个过滤器

  1. public class MsgProcessor {
  2. /**
  3. * 字符串信息
  4. */
  5. String msg;
  6. public MsgProcessor(String msg) {
  7. this.msg = msg;
  8. }
  9. /**
  10. * 过滤信息
  11. *
  12. * @return
  13. */
  14. public String process() {
  15. String str = msg;
  16. //过滤msg中的HTML标记
  17. str = str.replace("<", "&lt;").replace(">", "&gt;");
  18. //过滤敏感词
  19. str = str.replace("敏感", "");
  20. return str;
  21. }
  22. }

将过滤的方法都放在process方法中,这样不遵循开闭原则,修改过滤规则容易引起错误;

提取出过滤接口

  1. public interface StringFilter {
  2. /**
  3. * 过滤操作
  4. *
  5. * @param msg 源字符串
  6. * @return 过滤后字符串
  7. */
  8. String doFilter(String msg);
  9. }

实现过滤HTML标记

  1. public class HtmlFilter implements StringFilter {
  2. @Override
  3. public String doFilter(String msg) {
  4. msg = msg.replace("<", "&lt;").replace(">", "&gt;");
  5. return msg;
  6. }
  7. }

过滤处理

  1. public class MsgProcessor {
  2. /**
  3. * 字符串信息
  4. */
  5. String msg;
  6. List<StringFilter> filterList = new ArrayList<>();
  7. public MsgProcessor(String msg) {
  8. this.msg = msg;
  9. }
  10. /**
  11. * 过滤信息
  12. *
  13. * @return
  14. */
  15. public String process() {
  16. String str = msg;
  17. for (StringFilter filter : filterList) {
  18. str = filter.doFilter(str);
  19. }
  20. return str;
  21. }
  22. /**
  23. * 添加过滤方法
  24. *
  25. * @param filter
  26. */
  27. public void addFilter(StringFilter filter) {
  28. filterList.add(filter);
  29. }
  30. }

调用

  1. MsgProcessor msgProcessor=new MsgProcessor(":),敏感信息,<script>");
  2. msgProcessor.addFilter(new HtmlFilter());
  3. msgProcessor.process();

新增过滤方法只需要实现接口就好了

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注