@Tyhj
        
        2019-02-14T03:42:28.000000Z
        字数 2671
        阅读 1027
    设计模式
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
- 多个对象可以处理同一请求,但具体由那个对象处理则在运行时动态决定
 - 在请求处理者不确定的情况下向多个对象中的一个提交一个请求
 - 需要动态的指定一组对象处理请求
 
感觉很简单,不管下面如何去实现,只要构建了一条链,把请求按照这条链传递下去,避免请求者和接收者之间的耦合,就是责任链模式
网上最多的例子,解决审批权限问题;过年我要请假在家里多玩几天,请一个月假,项目经理说他最多审批2天的,多了找主管,主管说,一个月太过分了,他只能审批5天以内的,一个月要找老板,找老板,老板说小问题,准了;
用户接口
public interface User {/*** 请假审批*/void approval();}
请假类
public class Vacation {/*** 请假天数*/int days;public Vacation(int days) {this.days = days;}}
去请假
public void leave(Vacation vacation) {User boss=new Boss();User director=new Director();User manager=new Manager();if (vacation.days <= 2) {manager.approval();} else if (vacation.days <= 5) {director.approval();} else {boss.approval();}}
这个写法肯定是有问题的吧,看到if-else就知道是不符合开闭原则,修改容易引起错误;而且代码臃肿;具体的处理逻辑我们放到了这个场景类里面也不是很合理,应该放到各个用户中处理
修改用户接口
public abstract class User {/*** 上一级领导*/protected User nextUser;/*** 处理请假** @param vacation 请假*/public final void handleRequest(Vacation vacation) {if (vacation.days <= limit()) {approval();} else {if (null != nextUser) {nextUser.handleRequest(vacation);}}}/*** 能审批的天数** @return 天数*/public abstract int limit();/*** 请假审批*/public abstract void approval();}
主管实现类,其他差不多
public class Director extends User {@Overridepublic int limit() {return 5;}@Overridepublic void approval() {System.out.println("主管审批通过");}}
去请假
public void leave(Vacation vacation) {User boss=new Boss();User director=new Director();User manager=new Manager();manager.nextUser=director;director.nextUser=boss;manager.handleRequest(vacation);}
1.责任链模式与 if-else 相比,耦合性要低一些,因为它将条件判定分散到各个处理类中,并且这些处理类的优先处理顺序可以随意的设定,并且如果想要添加新的 handler 类也是十分简单的,这符合开放闭合原则。 
2.责任链模式感觉也更灵活,思路更清晰一些
标准的责任链模式,一个请求只能被一个节点处理,感觉其实应用的场景不是很多;一个请求被多个节点处理的场景要多一个,其实做法是差不多的;比如实现一个过滤器
public class MsgProcessor {/*** 字符串信息*/String msg;public MsgProcessor(String msg) {this.msg = msg;}/*** 过滤信息** @return*/public String process() {String str = msg;//过滤msg中的HTML标记str = str.replace("<", "<").replace(">", ">");//过滤敏感词str = str.replace("敏感", "");return str;}}
将过滤的方法都放在process方法中,这样不遵循开闭原则,修改过滤规则容易引起错误;
提取出过滤接口
public interface StringFilter {/*** 过滤操作** @param msg 源字符串* @return 过滤后字符串*/String doFilter(String msg);}
实现过滤HTML标记
public class HtmlFilter implements StringFilter {@Overridepublic String doFilter(String msg) {msg = msg.replace("<", "<").replace(">", ">");return msg;}}
过滤处理
public class MsgProcessor {/*** 字符串信息*/String msg;List<StringFilter> filterList = new ArrayList<>();public MsgProcessor(String msg) {this.msg = msg;}/*** 过滤信息** @return*/public String process() {String str = msg;for (StringFilter filter : filterList) {str = filter.doFilter(str);}return str;}/*** 添加过滤方法** @param filter*/public void addFilter(StringFilter filter) {filterList.add(filter);}}
调用
MsgProcessor msgProcessor=new MsgProcessor(":),敏感信息,<script>");msgProcessor.addFilter(new HtmlFilter());msgProcessor.process();
新增过滤方法只需要实现接口就好了