什么是责任链模式?
责任链模式:如果有多个对象都有机会处理某个请求
(至少有一个我们需要关注的指标,如,是否满足某个价格等),
责任链可以使请求的发送者与接受者解耦,请求沿责任链传递,直到有一个处理了它为止
责任链,顾名思义:判断是不是我的责任,如果是,处理请求,否则扔给下一个,
下一个对象判断是不是它的责任,如果不是,继续扔,直到有一个对象处理了该请求为止
of course,责任链,既然是链,那么这个链可以是线性的,也可以是环状的,也可是树形
毕竟你是上帝,下面的子民长得咋滴,你想怎么设计就怎么设计,你说了算图片
如:公司员工提交了申请的申请,可能要经过技术副组长-->技术组长-->小领导-->大领导
的审批才能通过申请。这个过程,可能技术副组长就有这个资格,直接通过了申请
也可能技术副组长和技术组长都没资格,小领导甚至是大领导才有资格
优点:
1、降低耦合度。它将请求的发送者和接收者解耦。
2、简化了对象。使得对象不需要知道链的结构。
3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许
动态地新增或者删除责任链中的节点。
4、增加新的请求处理类很方便。
缺点:
1、不能保证请求一定被接收。
2、请求从链的开头进行遍历,对性能有一定的损耗
3、在进行代码调试时不太方便,可能会造成循环调用。
4、可能不容易观察运行时的特征,有碍于除错。
1、在不明确指定接收者的情况下,提交一个请求给多个对象处理。
2、可动态指定一组对象处理某个请求,具体哪个对象处理该请求由运行时刻自动确定。
3、在使用策略模式的地方,可以考虑用责任链
在JAVA WEB中有些运用:
如:Interceptor拦截器,servlet中的Filter过滤器、FilterChain过滤器链
package design_pattern.chain;
/**
* 审批人
* 核心目标:
* 1.要实现链条,必须知道下个一个,所以要内置后续审批人属性
* 2.审批人有审批通过和不通过,满足条件通过则结束,不通过则交个下一个,该实现逻辑由子类去实现
* 父类只定义方法参数,父类的方法参数如果是对象类型,则该参数一般也是抽象类或接口,这叫面向抽象/接口编程
*/
public abstract class Approver {
//后续审批人
protected Approver successor;
//审批人姓名
protected String name;
public Approver(String name) {
this.name = name;
}
public void setSuccessor(Approver successor) {
this.successor = successor;
}
/**
* 处理申请请求的抽象方法 有请假申请、有提薪申请等等,所以这里应该使用抽象解耦
* 面向对象、面向接口、面向抽象、面向切面编程
* @param request
*/
public abstract void doRequest(Request request);
}
package design_pattern.chain;
/**
* 技术副组长:申请天数1~3天交给技术副组长
*/
public class DeputyGroupLeaderApprover extends Approver {
public DeputyGroupLeaderApprover(String name) {
super(name);
}
@Override
public void doRequest(Request request) {
if (request.getNums()>= 1 && request.getNums() <= 3) {//如果有审批资格
System.out.println(String.format("%s,审批通过,审批人:%s",request.toString(),name));
} else {//否则扔给下一个审批人
if(successor!=null)
successor.doRequest(request);
}
}
}
package design_pattern.chain;
/**
* 技术组长:申请天数4~6天交给技术组长
*/
public class GroupLeaderApprover extends Approver {
public GroupLeaderApprover(String name) {
super(name);
}
@Override
public void doRequest(Request request) {
if (request.getNums()>= 4 && request.getNums() <= 6) {//如果有审批资格
System.out.println(String.format("%s,审批通过,审批人:%s",request.toString(),name));
} else {//否则扔给下一个审批人
if(successor!=null)
successor.doRequest(request);
}
}
}
package design_pattern.chain;
/**
* 小领导:申请天数7~9天交给小领导
*/
public class SmallLeaderApprover extends Approver {
public SmallLeaderApprover(String name) {
super(name);
}
@Override
public void doRequest(Request request) {
if (request.getNums()>= 7 && request.getNums() <= 9) {//如果有审批资格
System.out.println(String.format("%s,审批通过,审批人:%s",request.toString(),name));
} else {//否则扔给下一个审批人
if(successor!=null)
successor.doRequest(request);
}
}
}
package design_pattern.chain;
/**
* 大领导:申请天数10~12天交给大领导
*/
public class BigLeaderApprover extends Approver {
public BigLeaderApprover(String name) {
super(name);
}
@Override
public void doRequest(Request request) {
if (request.getNums()>= 10 && request.getNums() <= 12) {
System.out.println(String.format("%s,审批通过,审批人:%s",request.toString(),name));
} else {//否则扔给下一个审批人
if(successor!=null)
successor.doRequest(request);
}
}
}
面向对象四大特性:封装、继承、多态、抽象
第一步:将请求封装成对象,是对象就要考虑属性和行为【方法】
package design_pattern.chain;
import java.time.LocalDateTime;
import java.util.StringJoiner;
/**
* 面向对象四大特性:封装、继承、多态、抽象
* 第一步:将请求封装成对象,是对象就要考虑属性和行为【方法】
*/
public abstract class Request {
//申请人
protected String name;
//申请时间
protected LocalDateTime applyTime;
//申请原因
protected String reason;
//申请天数
protected int nums;
public Request(){
}
public Request(String name, LocalDateTime applyTime, String reason, int nums) {
this.name = name;
this.applyTime = applyTime;
this.reason = reason;
this.nums = nums;
}
public int getNums() {
return nums;
}
/**
* 申请类型
*/
public abstract String applyType();
@Override
public String toString() {
return new StringJoiner(", ", Request.class.getSimpleName() + "[", "]")
.add("申请人='" + name + "'")
.add("申请时间=" + applyTime)
.add("申请原因='" + reason + "'")
.add("申请数量=" + nums)
.toString();
}
}
package design_pattern.chain;
import java.time.LocalDateTime;
public class AskForLeaveRequest extends Request {
public AskForLeaveRequest(String name, LocalDateTime applyTime, String reason, int nums) {
super(name, applyTime, reason, nums);
}
@Override
public String applyType() {
return "请假成申请";
}
}
package design_pattern.chain;
import java.time.LocalDateTime;
public class MainTest {
public static void main(String[] args) {
Approver deputy= new DeputyGroupLeaderApprover("技术副组长");
Approver group= new GroupLeaderApprover("技术组长");
Approver small= new SmallLeaderApprover("小领导");
Approver big= new BigLeaderApprover("大领导");
//设置后续申请人
deputy.setSuccessor(group);
group.setSuccessor(small);
small.setSuccessor(big);
big.setSuccessor(null);
//发起申请
Request request = new AskForLeaveRequest("张三",LocalDateTime.now(),"生病请假",5);
deputy.doRequest(request);
//由于我们使用的是面向抽象编程,
// 后期如果张三有调薪的请求,只需要新增一个调薪类,然后实体类替换即可
//原有的代码不用改动,只需要替换一处,体现了开闭原则
}
}
结果
学到了就要教人,赚到了就要给人!
The more I think, the luckier I am.
【越思考,越幸运】
斗皇强者,恐怖如斯,嘿嘿~~