1 概述
又称职责链模式(击鼓传花),为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
职责链模式主要包含以下角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
2 例子
请假流程控制系统,请假一天以下的假只需要小组长同意即可;请假1天到3天的假还需要部门经理同意;请求3天到7天还需要总经理同意才行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
| public class LeaveRequest { private String name; private int num; private String content;
public LeaveRequest(String name, int num, String content) { this.name = name; this.num = num; this.content = content; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getNum() { return num; }
public void setNum(int num) { this.num = num; }
public String getContent() { return content; }
public void setContent(String content) { this.content = content; } }
public class GeneralManager extends Handler { public GeneralManager() { super(Handler.NUM_SEVEN); }
@Override protected void handleLeave(LeaveRequest leave) { System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("总经理审批:同意。"); } }
public class Manager extends Handler { public Manager() { super(Handler.NUM_THREE, Handler.NUM_SEVEN); } @Override protected void handleLeave(LeaveRequest leave) { System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("部门经理审批:同意。"); } }
public class GroupLeader extends Handler { public GroupLeader() { super(Handler.NUM_ONE, Handler.NUM_THREE); } @Override protected void handleLeave(LeaveRequest leave) { System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。"); System.out.println("小组长审批:同意。"); } }
public abstract class Handler { protected final static int NUM_ONE = 1; protected final static int NUM_THREE = 3; protected final static int NUM_SEVEN = 7;
private int numStart; private int numEnd;
private Handler nextHandler;
public Handler(int numStart) { this.numStart = numStart; }
public Handler(int numStart, int numEnd) { this.numStart = numStart; this.numEnd = numEnd; }
public void setNextHandler(Handler nextHandler) { this.nextHandler = nextHandler; }
public final void submit(LeaveRequest leave) { if (0 == this.numStart) { return; } if (leave.getNum() >= this.numStart) { this.handleLeave(leave); if (null != this.nextHandler && leave.getNum() > numEnd) { this.nextHandler.submit(leave); } else { System.out.println("流程结束"); } } }
protected abstract void handleLeave(LeaveRequest leave); }
public class TestClient { public static void main(String[] args) { LeaveRequest leave = new LeaveRequest("小明", 5, "婚假"); GroupLeader groupLeader = new GroupLeader(); Manager manager = new Manager(); GeneralManager generalManager = new GeneralManager();
groupLeader.setNextHandler(manager); manager.setNextHandler(generalManager); groupLeader.submit(leave); } }
|
3 优缺点
优点:
- 降低耦合度。它将请求的发送者和接收者解耦。
- 简化了对象。使得对象不需要知道链的结构。
- 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。
- 增加新的请求处理类很方便。
缺点:
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。
- 可能不容易观察运行时的特征,有碍于除错。