@Tyhj
2019-02-14T11:42:28.000000Z
字数 2671
阅读 817
设计模式
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
- 多个对象可以处理同一请求,但具体由那个对象处理则在运行时动态决定
- 在请求处理者不确定的情况下向多个对象中的一个提交一个请求
- 需要动态的指定一组对象处理请求
感觉很简单,不管下面如何去实现,只要构建了一条链,把请求按照这条链传递下去,避免请求者和接收者之间的耦合,就是责任链模式
网上最多的例子,解决审批权限问题;过年我要请假在家里多玩几天,请一个月假,项目经理说他最多审批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 {
@Override
public int limit() {
return 5;
}
@Override
public 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 {
@Override
public 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();
新增过滤方法只需要实现接口就好了