职责链模式:当一个请求有可能被多个对象处理,则将这些对象连成一条链,并沿着这条链传递请求,直到该请求被处理为止。
单看上图, 你肯定看不出职责链模式的特征, 先举一个例子来说明一下. 比如一个员工想加工资, 他首先会告知team leader, 如果在team leader授权范围之内,则他可以办到, 否则,就要请求上级来处理,最后直到老板, 于是很容易写出这样的代码来:
- public class Employee {
- private TeamLeader tl;
- private DeptManager deptMgr;
- private GeneralManager gm;
- private Boss boss;
- //some other properties
- public void addSalary(int x){
- if(x<=100){
- tl.addSalary(this, x);
- }
- else if(x<=500){
- deptMgr.addSalary(this, x);
- }
- else if(x<=800){
- gm.addSalary(this, x);
- }
- else{
- boss.addSalary(this, x);
- }
- }
- // some other methods
- }
这个代码中的if else带来了坏味道, 同时, Employee必须知道他的每一个上司,并使Employee和每一个处理者(他的上司)耦合在一起. 其实一个Employee一般来说只需要和他的直接上司打交道就可以了. 就如下时序图所示.
把Employee的上司连成一条链, 即team leader持有他的上司部门经理, 部门经理持有他的上司总经理, 总经理持有他的上司老板. 则Employee只需要知道team leader即可.
加薪代码:
- //
- public interface Supervisor {
- public void addSalary(Employee e, int added);
- }
- ///
- public class Employee {
- public String name;
- private Supervisor supervisor;
- public Employee(String name){
- this.name = name;
- }
- public void setSupervisor(Supervisor supervisor) {
- this.supervisor = supervisor;
- }
- public void addSalary(int added){
- if(supervisor!=null){
- supervisor.addSalary(this, added);
- }
- }
- }
- ///
- public class TeamLeader implements Supervisor{
- private Supervisor successor;
- public TeamLeader(Supervisor s){
- this.successor = s;
- }
- public void addSalary(Employee e, int added) {
- if(added<100){
- System.out.println("Team Leader: " + e.name + " want to add "
- + added + " salary, I can process it, done!");
- }
- else if(successor!=null){
- System.out.println("Team Leader: " + e.name + " want to add "
- + added + " salary, I can't process it, but my supervisor can do!");
- successor.addSalary(e, added);
- }
- }
- }
- ///
- public class DeptManager implements Supervisor{
- private Supervisor successor;
- public DeptManager(Supervisor s){
- this.successor = s;
- }
- public void addSalary(Employee e, int added) {
- if(added<500){
- System.out.println("Dept Manager: " + e.name + " want to add "
- + added + " salary, I can process it, done!");
- }
- else if(successor!=null){
- System.out.println("Dept Manager: " + e.name + " want to add "
- + added + " salary, I can't process it, but my supervisor can do!");
- successor.addSalary(e, added);
- }
- }
- }
- ///
- public class GeneralManager implements Supervisor{
- private Supervisor successor;
- public GeneralManager(Supervisor s){
- this.successor = s;
- }
- public void addSalary(Employee e, int added) {
- if(added<800){
- System.out.println("General Manager: " + e.name + " want to add "
- + added + " salary, I can process it, done!");
- }
- else if(successor!=null){
- System.out.println("General Manager: " + e.name + " want to add "
- + added + " salary, I can't process it, but my supervisor can do!");
- successor.addSalary(e, added);
- }
- }
- }
- //
- public class Boss implements Supervisor{
- public Boss(){}
- public void addSalary(Employee e, int added) {
- //boss具有最终处理权限, 但是他打官腔
- System.out.println("Boss: I will process it soon.");
- }
- }
- /
- //测试用例
- public class Test {
- public static void main(String[] args) {
- Employee e = new Employee("Jack");
- Boss b = new Boss();
- GeneralManager gm = new GeneralManager(b);
- DeptManager dm = new DeptManager(gm);
- TeamLeader tl = new TeamLeader(dm);
- e.setSupervisor(tl);
- e.addSalary(1200);
- }
- }
- /
- //输出
- //Team Leader: Jack want to add 1200 salary, I can't process it, but my supervisor can do!
- //Dept Manager: Jack want to add 1200 salary, I can't process it, but my supervisor can do!
- //General Manager: Jack want to add 1200 salary, I can't process it, but my supervisor can do!
- //Boss: I will process it soon.
上面的代码有两个优点:
1 Employee不再依赖于具体的上司,转而依赖于抽象, 而且不必知道所有的上司;
2 如果新增了处理者, 只需要更改客户端代码, 即重新构造责任链就可以了.
基础代码:
- package designpattern.chainofresponsibility;
- public abstract class Handler {
- //注意修饰符为protected,因为子类要访问他
- protected Handler successor;
- public void setSuccessor(Handler successor) {
- this.successor = successor;
- }
- public abstract void handleRequest(int request);
- }
- //
- package designpattern.chainofresponsibility;
- public class ConcreteHandler1 extends Handler {
- public void handleRequest(int request) {
- if(request>=0&&request<10){
- System.out.println("request handled by ConcreteHandler1");
- return;
- }
- if(successor!=null){
- System.out.println("ConcreteHandler1 can't handle this request, dispatch to next.");
- successor.handleRequest(request);
- }
- }
- }
- //
- package designpattern.chainofresponsibility;
- public class ConcreteHandler2 extends Handler {
- public void handleRequest(int request) {
- if(request>=10&&request<20){
- System.out.println("request handled by ConcreteHandler2");
- return;
- }
- if(successor!=null){
- System.out.println("ConcreteHandler2 can't handle this request, dispatch to next.");
- successor.handleRequest(request);
- }
- }
- }
- //
- package designpattern.chainofresponsibility;
- public class ConcreteHandler3 extends Handler {
- public void handleRequest(int request) {
- if(request>=20&&request<30){
- System.out.println("request handled by ConcreteHandler3");
- return;
- }
- if(successor!=null){
- System.out.println("ConcreteHandler3 can't handle this request, dispatch to next.");
- successor.handleRequest(request);
- }
- }
- }
- //
- package designpattern.chainofresponsibility;
- public class ConcreteHandler4 extends Handler {
- public void handleRequest(int request) {
- if(request>=30){
- System.out.println("request handled by ConcreteHandler3");
- return;
- }
- }
- }
- //客户端测试用例
- package designpattern.chainofresponsibility;
- public class Client {
- public static void main(String[] args){
- Handler handler1 = new ConcreteHandler1();
- Handler handler2 = new ConcreteHandler2();
- Handler handler3 = new ConcreteHandler3();
- Handler handler4 = new ConcreteHandler4();
- handler1.setSuccessor(handler2);
- handler2.setSuccessor(handler3);
- handler3.setSuccessor(handler4);
- handler1.handleRequest(60);
- }
- }
责任链模式的关键点在于把请求的处理者连成一条链,一个处理者可以处理当前请求,也有权决定是否沿着链朝上传递请求.
优点:
1 可以简化对象之间的连接,他们只需要知道一个后继者就行了;
2 可以很方便的增加或修改处理者。
注意:
一个请求可以传递到末端都得不到处理,因此需要考虑全面。
经典案例:
jdk中我真的没有找到合适的例子,网上说Java 1.0版本中的AWT库采用责任链模式和命令模式来处理GUI的事件,我觉得有兴趣你可以看一下源码.DHTML中的事件处理机制可以看作职责链模式,这种机制又叫事件冒泡(Event Bubbling)机制, 当页面中的一个dom节点捕获一个事件(比如鼠标双击), 当前节点的处理函数可以处理改事件,然后也可以决定是否向上冒泡让父元素继续处理这个事件.浏览器的事件处理机制也是这样的。
如果你想到了j2ee中的Filter,或者spring中的Interceptor和ExecutionChain, 那你就错了. 因为就实现方法上看, Filter和Interceptor以及ExecutionChain都不是职责链模式.