小明是一家公司的员工, 因明天有事, 需要进行请假, 可批假的领导有部门负责人, 副总经理, 总经理等. 请 2 天以下部门负责人可以直接处理, 如果请 4 天以下的副总经理可以处理, 请 6 天以下就需要总经理处理. 这也是一个设计模式的体现, 那就是责任链模式.
责任链模式 (Chain of Responsibility) 使多个对象都有机会处理请求, 从而避免请求的发送者和接收者之间的耦合关系, 将这个对象连成一条链, 并沿着这条链传递该请求, 直到有一个对象处理它为止.(注: 责任链模式也叫职责链模式)
抽象处理者 (Handler) 角色
定义一个处理请求的接口, 包含抽象处理方法和一个后继连接.
具体处理者 (Concrete Handler) 角色
实现抽象处理者的处理方法, 判断能否处理本次请求, 如果可以处理请求则处理, 否则将该请求转给它的后继者.
客户类 (Client) 角色
创建处理链, 并向链头的具体处理者对象提交请求, 它不关心处理细节和请求的传递过程.
类图
抽象处理者
- public abstract class Handler {
- protected Handler successor;
- public void setSuccessor(Handler successor) {
- this.successor = successor;
- }
- public abstract void HandleRequest (int request) ;
- }
具体处理者
- public class ConcreteHandler1 extends Handler {
- @Override
- public void HandleRequest(int request) {
- if (request>= 0 && request <10) {
- System.out.println("ConcreteHandler1 处理请求"+request);
- } else if (successor != null) {
- // 让下一个负责人继续处理
- successor.HandleRequest(request);
- }
- }
- }
- public class ConcreteHandler2 extends Handler {
- @Override
- public void HandleRequest(int request) {
- if (request>= 10 && request<20) {
- System.out.println("ConcreteHandler2 处理请求:"+request);
- } else if (successor !=null) {
- successor.HandleRequest(request);
- }
- }
- }
- public class ConcreteHandler3 extends Handler {
- @Override
- public void HandleRequest(int request) {
- if (request>=20 && request<30) {
- System.out.println("ConcreteHandler3 处理请求:"+request);
- } else if (successor !=null) {
- successor.HandleRequest(request);
- }
- }
- }
测试类
- public class HandlerTest {
- public static void main(String[] args) {
- Handler h1 = new ConcreteHandler1();
- Handler h2 = new ConcreteHandler2();
- Handler h3 = new ConcreteHandler3();
- h1.setSuccessor(h2);
- h2.setSuccessor(h3);
- int[] requests = {2,5,14,22,18,3,27,20};
- for (int request:requests) {
- h1.HandleRequest(request);
- }
- }
- }
测试结果
ConcreteHandler1 处理请求 2
ConcreteHandler1 处理请求 5
ConcreteHandler2 处理请求: 14
ConcreteHandler3 处理请求: 22
ConcreteHandler2 处理请求: 18
ConcreteHandler1 处理请求 3
ConcreteHandler3 处理请求: 27
ConcreteHandler3 处理请求: 20
优点
责任链中的对象并不知道链的结构, 结果是责任链可简化对象的相互连接, 它们仅需要一个指向下一个解决者的引用, 而无需保持对象中所有情况都对接收者引用. 这也就打打降低了耦合度.
责任链模式比较灵活, 可以随时增加或者修改处理一个请求的结构, 增加了对象指派职责的灵活性.
责任分担, 每个类只需要处理自己的工作, 不该 处理传递给下一个对象完成, 明确各类的责任方位, 符合类的单一职责原则.
避免在一个类中使用众多的 if 或者 ifelse 语句.
缺点
一个请求极有可能到了链的末端都得不到处理, 或者因为没有正确配置而得不到处理. 这就很糟糕啦, 需要事先考虑全面.
在对于比较长的职责链, 请求处理可能涉及多个处理对象, 系统性能将会受到一定影响.
职责链建立合理性要靠客户端来保证, 增加了客户端的复杂性, 可能会由于责任链的错误设置导致系统出错, 如可能会造成循环调用.
在计算机软硬件中也有相关例子, 如总线网中数据报传送, 每台计算机根据目标地址是否同自己的地址相同来决定是否接收; 还有异常处理中, 处理程序根据异常的类型决定自己是否处理该异常; 还有 Struts2 的拦截器, JSP 和 Servlet 的 Filter 等, 所有这些, 如果用责任链模式都能很好解决.
假设小明想请 1 天假期的故事
领导抽象类
- public abstract class Leader {
- private Leader next;
- public void setNext(Leader next)
- {
- this.next=next;
- }
- public Leader getNext()
- {
- return next;
- }
- // 处理请求的方法
- public abstract void handleRequest(int LeaveDays);
- }
部门负责人实现类
- public class DepartmentsLeade extends Leader {
- @Override
- public void handleRequest(int leaveDays) {
- if (leaveDays <=2) {
- System.out.println("部门领导批准您请假" + leaveDays + "天.");
- } else {
- if(null != getNext()) {
- getNext().handleRequest(leaveDays);
- } else {
- System.out.println("请假天数太多, 没有人批准该假条!");
- }
- }
- }
- }
副经理实现类
- public class DeputyManagerLeader extends Leader {
- @Override
- public void handleRequest(int leaveDays) {
- if (leaveDays <=4) {
- System.out.println("副经理领导批准您请假" + leaveDays + "天.");
- } else {
- if (getNext() != null) {
- getNext().handleRequest(leaveDays);
- } else {
- System.out.println("请假天数太多, 没有人批准该假条!");
- }
- }
- }
- }
- public class ManagerLeader extends Leader {
- @Override
- public void handleRequest(int leaveDays) {
- if (leaveDays <=6) {
- System.out.println("经理领导批准您请假" + leaveDays + "天.");
- } else {
- if(null != getNext()) {
- getNext().handleRequest(leaveDays);
- } else {
- System.out.println("请假天数太多, 没有人批准该假条!");
- }
- }
- }
- }
测试类
- public class Test {
- public static void main(String[] args) {
- Leader leader1 = new DepartmentsLeade();
- Leader leader2 = new DeputyManagerLeader();
- Leader leader3 = new ManagerLeader();
- leader1.setNext(leader2);
- leader2.setNext(leader3);
- leader1.handleRequest(1);
- }
- }
测试结果
部门领导批准您请假 1 天.
小明最后成功请了一天假期, 看来设计模式无处不在呀.
注意啦! 往期设计模式在这里
来源: http://www.jianshu.com/p/8d437be1dcbe