责任链模式(Chain of Responsibility Pattren)属于是行为型模式。该模式构造一系列分别担当不同的职责的类对象来共同完成一个任务,这些类的对象之间像链条一样紧密相连,所以被称为责任链模式(或者职责链模式)
文章目录
责任链模式的介绍
责任链最基础的作用就是将一条指令依次传递给多个接收者处理,这些接收者可以是父子关系也可以是兄弟关系。
此模式分两个角色:发送者和接收者,首先将接收者排成一队(以“链表”的形式),当发送者发送一条指令后,先由第一个接收者接收指令,如果第一个接收者无法处理该指令则由第二个接收者接收,如此传递,直到这条指令被链表中的某个接收者执行后或者到达链尾结束。
优点
-
责任链模式降低了发出指令和处理指令对象之间的耦合
-
处理指令的类更专注于处理自己的事情,便于扩展和改变处理的优先级
-
允许动态地新增或者删除责任对象,方便扩展
缺点
-
责任对象过多会造成一定程度的延迟
-
不易观察运行时特征,调式代码时不方便
应用场景
- JS中的冒泡事件
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定
责任链模式的使用
举例:制作一个游戏的菜单,分别有开始游戏、环境设置、游戏帮助三个选项,系统根据玩家输入的指令来找到处理该指令的组件模块。
类图
责任链模式的实现方法
第一步:编写抽象处理类
GameMenu
package 设计模式.行为型模式.责任链模式;
public abstract class GameMenu {
protected GameMenu nextMenu; // 链中的下一个节点
/**
* 组成责任链的方法,将多个继承自GameMenu类的对象组合成链
* @param option
*/
public void addMenu(GameMenu option){
if (nextMenu != null) {
// 后面有对象时,将新入链的对象往后继续传递
nextMenu.addMenu(option);
}
else {
// 后面没对象时,将新对象入链
nextMenu = option;
}
}
/**
* 抽象执行方法
* @param instruct 字符串指令
*/
public abstract void execute(String instruct);
/**
* 当前接收者不匹配指令时,将指令传递个下一个接受者
* @param instruct
*/
public void next(String instruct){
// 下一个接受者存在则传递指令,不存在则返回提示信息
if (nextMenu!=null) nextMenu.execute(instruct);
else System.out.println("您输入的是无效指令!");
}
}
第二步:编写具体处理者
StartMenu
package 设计模式.行为型模式.责任链模式;
public class StartMenu extends GameMenu {
@Override
public void execute(String instruct) {
if (!instruct.equals("开始游戏")){
// 玩家指令不是“开始游戏”时,交由下一个接受者除了指令
next(instruct);
return;
}
System.out.println("游戏开始执行!");
}
}
SettingMenu
package 设计模式.行为型模式.责任链模式;
public class SettingMenu extends GameMenu {
@Override
public void execute(String instruct) {
if (!instruct.equals("打开设置")){
// 玩家指令不是“打开设置”时,交由下一个接受者除了指令
next(instruct);
return;
}
System.out.println("环境设置模块开始执行!");
}
}
HelpMenu
package 设计模式.行为型模式.责任链模式;
public class HelpMenu extends GameMenu {
@Override
public void execute(String instruct) {
if (!instruct.equals("打开帮助")){
// 玩家指令不是“打开帮助”时,交由下一个接受者除了指令
next(instruct);
return;
}
System.out.println("帮助模块开始执行!");
}
}
第三步:编写客户程序
Main
package 设计模式.行为型模式.责任链模式;
import java.util.Scanner;
public class Main {
// 模拟客户程序,在此类中调用实现责任链模式的对象
public static void main(String[] args) {
// 新建游戏菜单,他包含三个接收者对象:开始、环境、帮助
GameMenu gameMenu = new StartMenu();
gameMenu.addMenu(new SettingMenu());
gameMenu.addMenu(new HelpMenu());
// 与玩家交互
System.out.print("请输入指令:");
Scanner scanner = new Scanner(System.in);
String instruct = scanner.next();
// 按照玩家指令开始寻找匹配的对象进行执行
gameMenu.execute(instruct);
}
}
第四步:测试
输入:打开帮助
请输入指令:打开帮助
帮助模块开始执行!
Process finished with exit code 0
输入:打开设置
请输入指令:打开设置
环境设置模块开始执行!
Process finished with exit code 0
输入:开始游戏
请输入指令:开始游戏
游戏开始执行!
Process finished with exit code 0
输入无效指令:开始
请输入指令:开始
您输入的是无效指令!
Process finished with exit code 0