目录
一、责任链模式的介绍
1、定义
责任链模式使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。它将这些对象连成一条链,并沿着这条链传递请求,直到有对象处理它为止。责任链模式的重点在“链”上,由一条链去处理相似的请求,在链中决定谁来处理这个请求,并返回相应的结果。
责任链模式的两个角色:
- 抽象处理者角色(Handler):该角色对请求进行抽象,并定义一个方法以设定和返回对下一个处理者的引用。
- 具体处理者角色(ConcreteHandler):该角色接收到请求后,可以选择将请求处理掉,或者将请求传给下一个处理者。由于具体处理者持有对下一个处理者的引用,因此,如果需要,具体处理者可以访问下一个处理者。
责任链模式的类图如下:
2、使用场景
- 一个请求需要一系列处理工作。
- 业务流的处理,例如:文件审批。
- 对系统进行补充扩展。
3、优缺点
(1)优点
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
(2)缺点
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。
二、责任链模式的实现
场景描述:击鼓传花。这是一种饮酒游戏,在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传话的地方是分开的,以示公正。开始击鼓时,花束依次开始传递,鼓声一落,如果花束在某人手中,那他就得喝酒。
在责任链模式中,很多的对象由每一个对象对其下家的引用连接起来形成一条链,请求在这个链上传递,直到链上的某个对象决定处理此请求。对于发出这个请求的客户端来说,它并不知道链上的哪一个对象最终会处理该请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任,而这种方式很符合责任链模式。参加游戏的人是一个个具体的处理者对象,击鼓的人便是客户端对象。花代表酒令,是传向处理者的请求,每一个参加游戏的人在接到传来的花时,可选择的行为只有两个:将花向下传递;执行酒令喝酒。当某人执行了酒令之后,游戏重新开始,而击鼓的人并不知道最终是由哪一个做游戏的人执行酒令。
类图如下:
实现如下:
/**
* 传花者:抽象handler角色,定义出参加游戏的传花人要遵守的规则
*/
public abstract class Player {
private Player successor;
public abstract void handle(int i);
protected void setSuccessor(Player successor){
this.successor = successor;
}
/**
* 传给下一个
* @param index
*/
public void next(int index){
if(successor != null){
successor.handle(index);
}else{
System.out.println("游戏结束");
}
}
}
/**
* 具体传花者:PlayerA,每一个传花者都知道下家是谁,或者选择执行酒令,或者传花
*/
public class PlayerA extends Player{
public PlayerA(Player successor) {
this.setSuccessor(successor);
}
@Override
public void handle(int i) {
if(i == 1){
System.out.println("PlayerA 喝酒");
}else {
System.out.println("PlayerA 把花向下传");
next(i);
}
}
}
/**
* 具体传花者:PlayerB,每一个传花者都知道下家是谁,或者选择执行酒令,或者传花
*/
public class PlayerB extends Player{
public PlayerB(Player successor) {
this.setSuccessor(successor);
}
@Override
public void handle(int i) {
if(i == 2){
System.out.println("PlayerB 喝酒");
}else {
System.out.println("PlayerB 把花向下传");
next(i);
}
}
}
/**
* 具体传花者:PlayerC,每一个传花者都知道下家是谁,或者选择执行酒令,或者传花
*/
public class PlayerC extends Player{
public PlayerC(Player successor) {
this.setSuccessor(successor);
}
@Override
public void handle(int i) {
if(i == 3){
System.out.println("PlayerC 喝酒");
}else {
System.out.println("PlayerC 把花向下传");
next(i);
}
}
}
/**
* 具体传花者:PlayerD,每一个传花者都知道下家是谁,或者选择执行酒令,或者传花
*/
public class PlayerD extends Player{
public PlayerD(Player successor) {
this.setSuccessor(successor);
}
@Override
public void handle(int i) {
if(i == 4){
System.out.println("PlayerD 喝酒");
}else {
System.out.println("PlayerD 把花向下传");
next(i);
}
}
}
public class DrumBeater {
public static void main(String[] args) {
Player player = new PlayerA(new PlayerB(new PlayerC(new PlayerD(null))));
player.handle(3);
}
}