JavaScript 23 种设计模式之 16 责任链模式
- 概念与特点
- 结构与实现
- 应用场景
- 应用实例
- 总结
概念与特点
概念:
责任链模式指的是将一系列可以处理请求的对象组成一条链。当请求发生时,将请求沿着这条链传递,直到有对象处理为止。
特点:
- 使请求发送者和请求处理者解耦。
- 增强系统的拓展性,可以很方便地增加新的请求处理类,符合开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序。
- 责任链简化了对象之间的连接,每个对象只保留一个指向后继者的引用。避免了众多的if…else。
- 责任分担,每个类只处理自己改处理的工作。不改处理的工作传递给下一个对象完成。符合单一责任原则。
结构与实现
责任链模式抽象处理者、具体处理者、客户类。
抽象处理者:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
具体处理者:实现了抽象处理者的抽象方法,判断能否处理该请求,不能处理则转给后继者。
客户类:创建处理链,并将链头的具体处理对象提交请求。不关心处理细节和请求的传递过程。
案例:实现一个学生请求批准流程。当请假天数小于或等于2天时,由班主任批准;当请假天数小于或等于7天时,由系主任批准;当请假天数小于或等于10天时,由院长批准;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>React App</title>
</head>
<body>
<script>
class Leader{
setLeader(leader){
this.leader = leader;
}
getLeader(){
return this.leader;
}
handlerRequest(leaveDay){
}
}
class Adviser extends Leader{
handlerRequest(leaveDay){
if(leaveDay <= 2){
console.log('班主任批准'+leaveDay+"天")
}else {
if(this.getLeader()!==null){
this.getLeader().handlerRequest(leaveDay)
}else {
console.log('请假天数太多,没有人批准该假条!');
}
}
}
}
class DepartmentHead extends Leader{
handlerRequest(leaveDay){
if(leaveDay <= 7){
console.log('系主任批准'+leaveDay+"天")
}else {
if(this.getLeader()!==null){
this.getLeader().handlerRequest(leaveDay)
}else {
console.log('请假天数太多,没有人批准该假条!');
}
}
}
}
class Dean extends Leader{
handlerRequest(leaveDay){
if(leaveDay <= 10){
console.log('院长批准'+leaveDay+"天")
}else {
if(this.getLeader()!==null){
this.getLeader().handlerRequest(leaveDay)
}else {
console.log('请假天数太多,没有人批准该假条!');
}
}
}
}
class Customer{
static main(){
let handler1 = new Adviser();
let handler2 = new DepartmentHead();
let handler3 = new Dean();
handler1.setLeader(handler2);
handler2.setLeader(handler3);
handler1.handlerRequest(5);
}
}
Customer.main();
</script>
</body>
</html>
应用场景
- 有多个对象可以处理一个请求,那个对象处理请求是由运行时决定的。
- 可动态指定一组对象处理请求,或添加新的处理者。
- 在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
应用实例
暂无。
总结
责任链模式非常适合类似【批准流程】的应用场景。可以很方便地将节点层层传递。流程的使用者也不需要关注流程的具体实现或传递过程。将使用者与调用者很好地解耦。
【抽象处理类】:
1、提供 setNext 和 getNext 设置和获取下一个具体处理类的方法。
【具体处理类】:
1、判断业务参数是否处理该请求,否则转入下一个处理者。
【客户类】:
1、实例化每一个具体处理类,通过 setNext 依次转入下一个处理者。
2、将业务参数传入,调用第一个处理者的请求方法。