责任链(Chain of Responsibility)模式
责任链模式是一种对象行为模式。
在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。
发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
责任链模式的角色:
1、抽象处理者角色:定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由
一个java抽象类或者java接口实现。
2、具体处理者角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家,由于具体处理者持有对下家的引用,因此
,如果需要,具体处理者可以访问下家。
Java代码 收藏代码
//抽象处理者 public abstract class Hander{ //处理方法,调用此方法处理请求 protected Handle successor; public abstract void handleRequest(); //调用此方法,设定下家 public void setSuccessor(Handler successor){ this.successor = successor; } public Handler getSuccessor(){ return successor; } } //具体处理者 public class ConcreteHandler extends Handler{ public void handlerRequest(){ if(getSuccessor() != null){ System.out.println("The request is passed to " + getSuccessor()); getSuccessor().handlerRequest(); }else{ System.out.println("The request is handled here."); } } } //客户端 public class Client{ private static Handler handler1, handler2; public static void main(String args[]){ handler1 = new ConcreteHandler(); handler2 = new ConcreteHandler(); handler1.setSuccessor(handler2); handler1.handleRequest(); } }
纯的与不纯的责任链模式
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个:一是承担责任,二是把责任推给下家。
不允许出现某一个具体处理者对象在承担了一部分责任后又把责任向下传的情况。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接受,在一个不纯的责任链模式里面,一个请求可以最终不被
任何接受端对象所接收。
Java代码 收藏代码
//一个贾家击鼓传花喝酒的例子 //击鼓者(客户端) public class DrumBeater{ private static Player player; public static void main(String[] args){ //创建责任链 player = new JiaMu(new JiaShe(new JiaZheng(new JiaBaoYu(new JiaHuan(null))))); //规定由第四个处理者处理请求 player.handler(4); } } 抽象传花者 public abstract class Player{ public abstract void handler(int i); private Player successor; public Player(){ successor = null; } protected void setSuccessor(Player aSuccessor){ successor = aSuccessor; } //将花传给下家,如果没有下家,系统停止运行 public void next(int index){ //判断下家对象是否有效 if(successor != null){ //将请求传给下家 successor.handler(index); }else{ //系统停止运行 System.out.println("Program terminated."); System.exit(0); } } } //JiaMu类 public class JiaMu extends Player{ public JiaMu(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handler(int i){ if(i == 1){ System.out.println("Jia Mu gotta drink!"); }else{ System.out.println("JiaMu passed!"); next(i); } } } //JiaShe public class JiaShe extends Player{ public JiaShe(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handler(int i){ if(i == 2){ System.out.println("Jia She gotta drink!"); }else{ System.out.println("Jia She passed!"); next(i); } } } public class JiaZheng extends Player{ public JiaZheng(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handler(int i){ if(i == 3){ System.out.println("Jia Zheng gotta drink!"); }else{ System.out.println("Jia Zheng passed!"); next(i); } } } public class JiaBaoYu extends Player{ public JiaBaoYu(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handler(int i){ if(i == 4){ System.out.println("Jia Bao Yu gotta drink!"); }else{ System.out.println("Jia Bao Yu passed!"); next(i); } } } public class JiaHuan extends Player{ public JiaHuan(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handler(int i){ if(i == 5){ System.out.println("Jia Huan gotta drink!"); }else{ System.out.println("Jia Huan passed!"); next(i); } } }
在下面的情况下可以使用责任链模式:
(1)系统已经有一个由处理者对象组成的链。这个链可能由合成模式给出。
(2)有多于一个的处理者对象会处理一个请求,而且事先并不知道到底由哪一处理者对象处理一个请求。
这个处理者对象是动态确定的。
(3)系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会处理此请求。
(4)处理一个请求的处理者对象的集合需要动态地指定时。
责任链模式降低了发出命令的对象和处理命令的对象之间的耦合,它允许多于一个的处理者对象根据自己的逻辑来决定
哪一个处理者最终处理这个命令。换言之,发出命令的对象只是把命令传给链结构的起始者,而不需要知道到底是链上
的哪一个节点处理了这个命令。
显然。这意味着在处理命令时,允许系统有更多的灵活性。哪一个对象最终处理一个命令可以因为由哪些对象参加责任链,
以及这些对象在责任链上的位置不同而有所不同。
Java代码 收藏代码
//一个使用Timer的例子 import java.util.Timer; import java.util.TimerTask; public class Reminder{ Timer timer; //构造子,在seconds秒后执行一个任务 public Reminder(int seconds){ timer = new Timer(); timer.schedule(new RemindTask(),seconds*1000); //schedule(清单,目录) } //内部成员类,描述将要执行的任务 class RemindTask extends TimerTask{ public void run(){ System.out.println("Time's up!"); timer.cancle(); } } public static void main(String[] args){ System.out.println("About to schedule task."); new Reminder(5); System.out.println("Task scheduled."); } } //Timer类是线程安全的,换言之,可以有多个线程共享同一个Timer对象,而不需要同步化。这是使用Timer的一个好处。 //击鼓者(相当于客户端) import java.lang.Thread; import java.util.Timer; import java.util.TimerTask; public class DrumBeater{ private static Player firstPlayer; public static boolean stopped = false; Timer timer; public static void main(String[] args){ DrumBeater drumBeater = new DrumBeater(); JiaMu jiaMu = new JiaMu(null); JiaMu.setSuccessor(new JiaShe(new JiaZheng(new JiaBaoYu(new JiaHuan(jiaMu))))); //开始击鼓过程 drumBeater.startBeating(1); //由贾母开始传花 firstPlayer = jiaMu; firstPlayer.handle(); } //调用下面方法,开始击鼓过程 public void startBeating(int stopInSeconds){ System.out.println("Drum beating started..."); timer = new Timer(); timer.schedule(new StopBeatingReminder(),stopInSeconds*1000); } //内部成员类,描述停止击鼓的任务 class StopBeatingReminder extends TimerTask{ public void run(){ System.out.println("Drum beating stopped!"); stopped = true; timer.cancel(); } } } //抽象传花者类 public abstract class Player{ public abstract void handle(); private Player successor; public Player(){ successor = null; } protected void setSuccessor(Player aSuccessor){ successor = aSuccessor; } public void next(){ //判断下家对象是否有效 if(successor != null){ //将请求传给下家 successor.handle(); }else{ //系统停止运行 System.out.println("Program is terminating."); System.exit(0); } } } //贾母 public class JiaMu extends Player{ public JiaMu(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handle(){ //检查是否击鼓已经停止] if(DrumBeater.stopped){ System.out.pritntln("Jia Mu gotta drink!"); }else{ System.out.println("Jia Mu passed!"); next(); } } } ...................... public class JiaHuan extends Player{ public JiaHuan(Player aSuccessor){ this.setSuccessor(aSuccessor); } public void handle(){ //检查是否击鼓已经停止] if(DrumBeater.stopped){ System.out.println("Jia Huan gotta drink!"); }else{ System.out.println("Jia Huan passed!"); next(); } } }