• 23种设计模式之责任链模式


    责任链模式是什么

    为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象的记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。

    在责任链模式中,客户只需要将请求发送到责任链上即可,无需关心请求的处理细节和请求的传递过程,请求会自动进行传递。所以责任链将请求的发送者和处理者解耦了。

    责任链模式的优缺点

    责任链模式是一种对象行为型模式,其主要优点如下:

    • 降低了对象之间的耦合度。该模型使得一个对象无需知道到底是哪一个对象处理其请求以及链的结构,发送者和接受者也无需拥有对方的明确信息。
    • 增强了系统的可扩展性。可根据需要增加新的请求处理类,满足开闭原则。
    • 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链条内的成员或者调用他们的次序,也可以动态地新增或者删除责任。
    • 责任链条简化了对象之间的连接。每个对象只需要保持一个指向其后继者的引用,不需要保持其所有处理者的引用,这避免了使用众多的 if 或者 if…else语句
    • 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

    其主要缺点如下:

    • 不能保证每个请求一定被处理。由于一个请求没有明确的接受者,所以不能保证它一定会被处理掉,该请求可能一直传递到链的末端都得不到处理。
    • 职责链比较长。对比较长的职责链,请求的处理可能涉及多个处理对象,会增加过多对象,而且会因为要等待链条处理完毕,会影响系统性能。
    • 职责链建立的合理性要考客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

    责任链模式的结构图

    责任链模式

    简单实现java代码

    public class LeaveApprovalTest {
    	public static void main(String[] args) {
    		//组装责任链
    		Leader teacher1 = new ClassAdviser();
    		Leader teacher2 = new DepartmentHead();
    		Leader teacher3 = new Dean();
    		//Leader teacher4=new DeanOfStudies();
    		teacher1.setNext(teacher2);
    		teacher2.setNext(teacher3);
    		//teacher3.setNext(teacher4);
    		//提交请求
    		teacher1.handleRequest(8);
    	}
    }
    
    //抽象处理者:领导类
    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);
    }
    
    //具体处理者1:班主任类
    class ClassAdviser extends Leader {
    	public void handleRequest(int LeaveDays) {
    		if (LeaveDays <= 2) {
    			System.out.println("班主任批准您请假" + LeaveDays + "天。");
    		} else {
    			if (getNext() != null) {
    				getNext().handleRequest(LeaveDays);
    			} else {
    				System.out.println("请假天数太多,没有人批准该假条!");
    			}
    		}
    	}
    }
    
    //具体处理者2:系主任类
    class DepartmentHead extends Leader {
    	public void handleRequest(int LeaveDays) {
    		if (LeaveDays <= 7) {
    			System.out.println("系主任批准您请假" + LeaveDays + "天。");
    		} else {
    			if (getNext() != null) {
    				getNext().handleRequest(LeaveDays);
    			} else {
    				System.out.println("请假天数太多,没有人批准该假条!");
    			}
    		}
    	}
    }
    
    //具体处理者3:院长类
    class Dean extends Leader {
    	public void handleRequest(int LeaveDays) {
    		if (LeaveDays <= 10) {
    			System.out.println("院长批准您请假" + LeaveDays + "天。");
    		} else {
    			if (getNext() != null) {
    				getNext().handleRequest(LeaveDays);
    			} else {
    				System.out.println("请假天数太多,没有人批准该假条!");
    			}
    		}
    	}
    }
    
    //具体处理者4:教务处长类
    class DeanOfStudies extends Leader {
    	public void handleRequest(int LeaveDays) {
    		if (LeaveDays <= 20) {
    			System.out.println("教务处长批准您请假" + LeaveDays + "天。");
    		} else {
    			if (getNext() != null) {
    				getNext().handleRequest(LeaveDays);
    			} else {
    				System.out.println("请假天数太多,没有人批准该假条!");
    			}
    		}
    	}
    }
    
    • 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

    模式的使用场景

    1. 多对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
    2. 可以动态指定一组对象处理请求,或添加新的处理者
    3. 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
  • 相关阅读:
    .NET 托管vs非托管
    Git常用命令
    数据治理要点
    【微信小程序】slider滑动选择器(82/100)
    Python编程陷阱(四)
    一幅长文细学Vue(六)——组件高级(下)
    18、Java的类变量、类方法;static 关键字;静态导入;初始化块;静态初始化块;单例模式
    C# List<T>.IndexOf()方法的使用
    【操作系统】内存管理
    用JMeter对HTTP接口进行压测(一)压测脚本的书写、调试思路
  • 原文地址:https://blog.csdn.net/Edcee300015/article/details/126011436