大家好,欢迎来到程序视点!我是小二哥。
今天和大家聊一聊软件设计中关系型模式的另一种强大模式:责任链模式(Chain of Responsibility)
。
还是把这张概总图放这里。
责任链模式,是一种行为模式。先来看下它的定义。
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
它描述的是请求发送者
和请求接受处理者
之间的关系。
请求接受处理者
不是一个对象,而是多个对象一起形成的链。
责任链模式,能够将多个对象组成一个链,并依次处理请求,直到有一个对象能够完全处理该请求为止。这里的每个对象被称为责任链的节点,每个节点都有两个基本操作:处理请求
和将请求转发给下一个节点
。
责任链模式是一种能够简化复杂逻辑处理的设计模式,常被用于处理请求、日志记录、异常捕获等场景。让我们一起来看看责任链模式是如何工作的,以及它为我们带来的便利。
让我们来看一看这个例子:请假条审批。
分析:假如规定请假小于或等于 2 天,主管可以批准;小于或等于 7 天,经理可以批准;小于或等于 10 天,总监可以批准;其他情况不予批准;
这个实例适合使用责任链模式实现。让我们一步一步的来看。
先准备好不同假期的批准对象。
主管准假
public class SupervisorHandler {
public boolean handler(int leaveDays){
if(leaveDays <= 2) {
System.out.println("小于或等于2-->主管准假!");
}
return leaveDays <= 2;
}
}
经理准假
public class ManagerHandler {
public boolean handler(int leaveDays){
if(leaveDays <= 7) {
System.out.println("小于或等于7-->经理准假!");
}
return leaveDays <= 7;
}
}
总监准假
public class DirectorHandler {
public boolean handler(int leaveDays){
if(leaveDays <= 10) {
System.out.println("小于或等于10-->总监准假!");
}
return leaveDays <= 10;
}
}
现在开始批假啦~
public class HandlerClient {
public static void main(String[] args) {
SupervisorHandler supervisorHandler = new SupervisorHandler();//主管
ManagerHandler managerHandler = new ManagerHandler();//经理
DirectorHandler directorHandler = new DirectorHandler();//总监
boolean isPermitted = supervisorHandler.handler();
//主管批不了,才到经理批
if(!isPermitted){
isPermitted = managerHandler.handler();
//经理批不了,才到总监批
if(!isPermitted){
isPermitted =directorHandler.handler();
//总监批不了,那回去歇着~没法批了
if(!isPermitted){
System.out.println("批不了~");
}
}
}
}
}
乍一看~代码执行也没有任何问题。但是这段代码扩展性非常不好,有很大的问题。问题主要如下:
1.假如现在要增加几个审批条件:小于或等于 15 天,CEO可以准假;小于或等于 30 天,总裁准假...随着条件增多,if条件的嵌套就增加啦~这样的代码非常糟糕!
2.上面准假的流程是我们来控制的,也就是每一步和下一步的审批逻辑是程序员自己来控制的。这里只有三、五个步骤,还比较好办。假如有10个审批步骤,现在要裁撤第3、第5、第6步骤,代码修改起来就非常麻烦--你必须修改整个流程。
如何接却上面的问题?在前面的简介中,我们说过: 每个对象被称为责任链的节点,每个节点都有两个基本操作:处理请求
和将请求转发给下一个节点
。
我们之前只做了处理请求
的操作,没有将请求转发给下一个节点
的操作。补上就可以啦~
将请求转发给下一个节点
,就是让每一个步骤都知道自己的下一个步骤是谁来处理!这样就形成了一条链--责任链的链呀!
修改如下:每一级领导在批假的时候,如果无权处理就将假条交给下一位具体处理者,直到最后;那就是每一级都需要知道自己的下一级。主管准假修改
public class SupervisorHandler {
private ManagerHandler next;
public void setNext(ManagerHandler next)
{
this.next=next;
}
public ManagerHandler getNext()
{
return next;
}
public boolean handler(int leaveDays){
if(leaveDays <= 2) {
System.out.println("小于或等于2-->主管准假!");
}
return leaveDays <= 2;
}
}
注意这里一个问题:SupervisorHandler 的下一级是 ManagerHandler,那 ManagerHandler 的下一级是 DirectorHandler,总不能每一级的下一级都用不同的类型吧?它们都是处理请假的!我们要抽象出来!
抽象出批假处理类--一个领导类,每一级具体的批假类都实现它
abstract class LeaderHander
{
private LeaderHander next;
public void setNext(LeaderHander next)
{
this.next=next;
}
public LeaderHander getNext()
{
return next;
}
//处理请求的方法
public abstract void handler(int LeaveDays);
}
ps:我们这里的 hander 方法不用有返回值,因为我们的判断逻辑放在批假类内部了,不需要在外部用 true or false 来判断往不往下一级走,而是在链上的每一级自己决定往不往下一步走!
主管最终修改类
public class SupervisorHandler extends LeaderHander {
public void handler(int leaveDays){
if(leaveDays <= 2) {
System.out.println("主管准假" + leaveDays + "天!");
} else {
if(getNext() != null) {
getNext().handler(leaveDays);
}else{
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
经理最终修改类
public class ManagerHandler extends LeaderHander {
public boolean handler(int leaveDays){
if(leaveDays <= 7) {
System.out.println("经理准假" + leaveDays + "天!");
} else {
if(getNext() != null) {
getNext().handler(leaveDays);
}else{
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
总监最终修改类
public class DirectorHandler extends LeaderHander {
public boolean handler(int leaveDays){
if(leaveDays <= 10) {
System.out.println("总监准假" + leaveDays + "天!");
} else {
if(getNext() != null) {
getNext().handler(leaveDays);
}else{
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
现在再来测试下:
public class LeaveApprovalTest{
public static void main(String[] args){
//组装责任链
LeaderHander supervisorHandler=new SupervisorHandler();
LeaderHander managerHandler=new ManagerHandler();
LeaderHander directorHandler=new DirectorHandler();
supervisorHandler.setNext(managerHandler);
managerHandler.setNext(directorHandler);
//处理请假审批
teacher1.handleRequest(8);
}
}
ps:我们组装了一个责任链:supervisorHandler --》managerHandler --》 directorHandler,然后把要处理的请求给到链上任意节点即可!最重要的是,我们处理请假审批时,再也没有 if 条件嵌套啦!
现在我们增加一个CEO准假类:
public class CEOHandler extends LeaderHander {
public boolean handler(int leaveDays){
if(leaveDays <= 10) {
System.out.println("CEO准假" + leaveDays + "天!");
} else {
if(getNext() != null) {
getNext().handler(leaveDays);
}else{
System.out.println("请假天数太多,没有人批准该假条!");
}
}
}
}
要使用这个类,把它加到链上去就可以啦!
LeaderHander ceoHandler=new CEOHandler();
directorHandler.setNext(ceoHandler);
每个节点都准备好了,这个责任链想怎么串就怎么串!扩展性好多啦~
责任链模式的好处在于,它将条件判断的逻辑分散到了各个节点中,使得代码更加清晰、可扩展和易于维护。非常适用于需要按照一定规则依次处理请求的场景。
来看下责任链模式的优缺点:
优点
主要缺点
好了,最后希望通过这篇能让你对责任链模式有个初步的了解,并在实际开发中灵活应用。如果您有任何问题或意见,请随时留言讨论。谢谢!