职责链涉及事务处理的传递问题,发出事务处理请求的对象到最终接收事务并进行处理的对象,它们之间可能还有一些参与传递事务处理请求的对象。GOF一书中的描述为:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。职责链是一种对象行为模式,下图是GOF给出的结构图。
下面这个例子是取自《Java与模式》一书,讲的是《红楼梦》中击鼓传花的故事,花传到谁的手中,谁就需要喝酒,传递方式是由贾母开始,依次是贾政、贾宝玉、贾环...,最后回到贾母,还要有一个人随机抽一张卡片,卡片上写一个数字,抽出哪个数字,就把花传给对应的人,如果没有该数字对应的人,则有Default类处理。如下图是该游戏的类图:
代码如下:
1 abstract class Player{ 2 abstract public void handle(int i); 3 private Player successor; 4 public Player(){ 5 successor=null; 6 } 7 protected void setSuccessor(Player asucc){ 8 successor=asucc; 9 } 10 public void next(int index){ 11 if(successor!=null){ 12 successor.handle(index); 13 }else{ 14 System.out.println("Program terminated"); 15 System.exit(0); 16 } 17 } 18 } 19 20 21 class JiaMu extends Player{ 22 public JiaMu(Player asucc){ 23 this.setSuccessor(asucc); 24 } 25 public void handle(int i){ 26 if(i==1){ 27 System.out.println("Jia Mu gotta drink"); 28 }else{ 29 System.out.println("Jia Mu Passed"); 30 next(i); 31 } 32 } 33 } 34 class JiaShe extends Player{ 35 public JiaShe(Player asucc){ 36 this.setSuccessor(asucc); 37 } 38 public void handle(int i){ 39 if(i==2){ 40 System.out.println("Jia She gotta drink"); 41 }else{ 42 System.out.println("Jia She Passed"); 43 next(i); 44 } 45 } 46 } 47 class JiaZheng extends Player{ 48 public JiaZheng(Player asucc){ 49 this.setSuccessor(asucc); 50 } 51 public void handle(int i){ 52 if(i==3){ 53 System.out.println("Jia Zheng gotta drink"); 54 }else{ 55 System.out.println("Jia Zheng Passed"); 56 next(i); 57 } 58 } 59 } 60 class JiaBaoYu extends Player{ 61 public JiaBaoYu(Player asucc){ 62 this.setSuccessor(asucc); 63 } 64 public void handle(int i){ 65 if(i==4){ 66 System.out.println("Jia BaoYu gotta drink"); 67 }else{ 68 System.out.println("Jia BaoYu Passed"); 69 next(i); 70 } 71 } 72 } 73 class JiaHuan extends Player{ 74 public JiaHuan(Player asucc){ 75 this.setSuccessor(asucc); 76 } 77 public void handle(int i){ 78 if(i==5){ 79 System.out.println("Jia Huan gotta drink"); 80 }else{ 81 System.out.println("Jia Huan Passed"); 82 next(i); 83 } 84 } 85 } 86 class Default extends Player{ 87 public Default(Player asucc){ 88 this.setSuccessor(asucc); 89 } 90 public void handle(int i){ 91 System.out.println("SomeOne gotta drink"); 92 System.exit(0); 93 } 94 } 95 public class Test{ 96 public static void main(String[] args) { 97 Player p=new JiaMu(new JiaZheng(new JiaBaoYu(new JiaHuan(new JiaShe(new JiaMu(new Default(null))))))); 98 p.handle(4); 99 p.handle(1); 100 p.handle(6); 101 } 102 }
其实,在该游戏中,可以形成一个环链,在实际应用当中,请求最终要被处理的,所以要设计好最后接收请求命令的那个功能模块。
在HTML中,事件的处理也用到了职责链模式,如下:
<html>
<body onclick="alert('document receives onclick event');">
<form name="myform" onclick="alert('myform receives onclick event');">
<input type=button name="mybutton" value="click here" onclick="alert('mybutton receives onclick event')">
</form>
</body>
</html>
当点击button时,提示窗口可以一层一层往上传递,这里面有职责链模式的思想。