GOF23设计模式之责任链模式(chain of responsibility)
一、责任链模式概述
将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求。
如果能则处理,否则传递给链上的下一个对象去处理。
定义责任链
(1)通过链表的方式实现职责链
(2)通过非链表的方式实现职责链
通过集合、数组生成职责链更加实用!实际上,很多项目中,每个具体的Handler并不是由开发团队定义的,而是项目上线后由外部单位追加的,所以使用链表方式定义责任链(COR)就很困难!
二、责任链模式场景
(1)公司里面,请假条审批过程:
① 如果请假天数小于3天,主任审批
② 如果请假天数大于等于3天,小于10天,经理审批
③ 如果请假天数大于等于10天,小于30天,总经理审批
④ 如果请假天数大于等于30天,提示拒绝
(2)添加新的处理对象:
可以在流程中增加新的“副总经理”角色,审批大于等于10天,小于20天的情况。
① 如果请假天数小于3天,主任审批
② 如果请假天数大于等于3天,小于10天,经理审批
③【增加】如果请假天数大于等于10天,小于20天,副总经理审批
④ 如果请假天数大于等于20天,小于30天,总经理审批
⑤ 如果请假天数大于等于30天,提示拒绝
三、使用责任链模式模拟公司请假流程
/**
* 封装请假的基本信息
* @author CL
*
*/
public class LeaveRequest {
/**
* 员工姓名
*/
private String empName;
/**
* 请假天数
*/
private int leaveDays;
/**
* 请假事由
*/
private String reason; public LeaveRequest() {
} public LeaveRequest(String empName, int leaveDays, String reason) {
this.empName = empName;
this.leaveDays = leaveDays;
this.reason = reason;
} public String getEmpName() {
return empName;
} public void setEmpName(String empName) {
this.empName = empName;
} public int getLeaveDays() {
return leaveDays;
} public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
} public String getReason() {
return reason;
} public void setReason(String reason) {
this.reason = reason;
} }
/**
* 抽象类(领导)
* @author CL
*
*/
public abstract class Leader {
protected String name;
/**
* 责任链上的后继对象
*/
protected Leader nextLeader; public Leader(String name) {
this.name = name;
} /**
* 设定责任链上的后即对象
* @param nextLeader
*/
public void setNextLeader(Leader nextLeader) {
this.nextLeader = nextLeader;
} /**
* 处理请假请求的核心业务方法
* @param leaveRequest
*/
public abstract void handlerRequest(LeaveRequest leaveRequest); }
/**
* 主任
* @author CL
*
*/
public class Director extends Leader { public Director(String name) {
super(name);
} @Override
public void handlerRequest(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays() < 3) {
System.out.println("员工:"+leaveRequest.getEmpName()+",请假:"
+leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
System.out.println("主任:"+this.name+",审批通过!");
} else { //责任链上的后继对象处理
if (this.nextLeader != null) {
this.nextLeader.handlerRequest(leaveRequest);
}
}
} }
/**
* 经理
* @author CL
*
*/
public class Manager extends Leader { public Manager(String name) {
super(name);
} @Override
public void handlerRequest(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays() < 10) {
System.out.println("员工:"+leaveRequest.getEmpName()+",请假:"
+leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
System.out.println("经理:"+this.name+",审批通过!");
} else { //责任链上的后继对象处理
if (this.nextLeader != null) {
this.nextLeader.handlerRequest(leaveRequest);
}
}
} }
/**
* 副总经理
* @author CL
*
*/
public class ViceGeneraManager extends Leader { public ViceGeneraManager(String name) {
super(name);
} @Override
public void handlerRequest(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays() < 20) {
System.out.println("员工:"+leaveRequest.getEmpName()+",请假:"
+leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
System.out.println("副总经理:"+this.name+",审批通过!");
} else { //责任链上的后继对象处理
if (this.nextLeader != null) {
this.nextLeader.handlerRequest(leaveRequest);
}
}
} }
/**
* 总经理
* @author CL
*
*/
public class GeneraManager extends Leader { public GeneraManager(String name) {
super(name);
} @Override
public void handlerRequest(LeaveRequest leaveRequest) {
if (leaveRequest.getLeaveDays() < 30) {
System.out.println("总经理:"+leaveRequest.getEmpName()+",请假:"
+leaveRequest.getLeaveDays()+"天,理由:"+leaveRequest.getReason());
System.out.println("主任:"+this.name+",审批通过!");
} else { //无责任链上的后继对象
System.out.println("员工:"+leaveRequest.getEmpName()+",请假天数:"
+leaveRequest.getLeaveDays()+"天,超过30天,不予请假!");
}
} }
测试:
/**
* 测试责任链模式
* @author CL
*
*/
public class Client { public static void main(String[] args) {
Leader a = new Director("张主任");
Leader b = new Manager("李经理");
Leader c = new ViceGeneraManager("王副总经理");
Leader d = new GeneraManager("赵总经理"); //构建责任链
a.setNextLeader(b);
b.setNextLeader(c);
c.setNextLeader(d); //请假
LeaveRequest req1 = new LeaveRequest("Tom", 2, "生病");
LeaveRequest req2 = new LeaveRequest("Jame", 15, "回家");
LeaveRequest req3 = new LeaveRequest("Rose", 25, "调休");
LeaveRequest req4 = new LeaveRequest("Jack", 35, "闹着玩"); //审批
a.handlerRequest(req1);
a.handlerRequest(req2);
a.handlerRequest(req3);
a.handlerRequest(req4);
}
}
控制台输出:
员工:Tom,请假:2天,理由:生病
主任:张主任,审批通过!
员工:Jame,请假:15天,理由:回家
副总经理:王副总经理,审批通过!
总经理:Rose,请假:25天,理由:调休
主任:赵总经理,审批通过!
员工:Jack,请假天数:35天,超过30天,不予请假!
四、责任链模式常见开发应用场景
(1)Java 中,异常处理机制就是一种责任链模式。一个 try 可以对应多个 catch,当第一个 catch 不匹配类型,则自动跳到第二个 catch;
(2)JavaScript 语言中,事件的冒泡和捕获机制(Java 语言中事件的处理采用观察者模式);
(3)Servlet 开发中,过滤器的链式处理;
(4)Struts2 中,拦截器的调用也是典型的责任链模式;
(5)…………
GOF23设计模式之责任链模式(chain of responsibility)的更多相关文章
- 乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern)
原文:乐在其中设计模式(C#) - 责任链模式(Chain of Responsibility Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 责任链模式(Chain of R ...
- 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)
责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...
- [设计模式] 13 责任链模式 Chain of Responsibility
转 http://blog.csdn.net/wuzhekai1985 http://www.jellythink.com/archives/878 向项目经理提交了休假申请,我的项目经理向 ...
- 设计模式 笔记 责任链模式 chain of responsibility
//---------------------------15/04/25---------------------------- //Chain of responsibility 责任链----- ...
- 责任链模式-Chain of Responsibility(Java实现), 例2
责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...
- 责任链模式-Chain of Responsibility(Java实现), 例1
责任链模式-Chain of Responsibility, 例1 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. ...
- 《JAVA设计模式》之责任链模式(Chain of Responsibility)
在阎宏博士的<JAVA与模式>一书中开头是这样描述责任链(Chain of Responsibility)模式的: 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其 ...
- 责任链模式/chain of responsibility/行为型模式
职责链模式 chain of responsibility 意图 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处 ...
- 【GOF23设计模式】责任链模式
来源:http://www.bjsxt.com/ 一.[GOF23设计模式]_责任链模式.公文审批.供应链系统的采购审批.异常链.过滤器和拦截器调用过程 package com.test.chainO ...
随机推荐
- sql复制表结构及复制表数据
一.复制表结构 假设我们有一个数据表Person,有Id,FirstName,LastName,Weight,Height5个列,表结构可以参考这一篇.现在我们想创建一个新表叫People,表结构和P ...
- Algorithm3: 获得一个int数中二进制位为1 的个数
获得一个int数中二进制位为1 的个数 int NumberOfOne(int n){ int count = 0; unsig ...
- c# 让double保留两位小数
1.Math.Round(0.333333,2);//按照四舍五入的国际标准2. double dbdata=0.335333; string str1=String.Format(&qu ...
- 重置input checked
<!-- 作者:duke 时间:2018-10-24 描述: 重置input 样式--> <!DOCTYPE HTML><html> <head> &l ...
- 【Html 学习笔记】第八节——表单实践
列举一些实践的例子: 1.点击按钮后跳转: <html> <body> <form action="1.html"> First <inp ...
- mysql的sql编程
sql编程 变量 变量分为两种:系统变量和自定义变量 系统变量 系统定义好的变量:大部分的时候用户根本不需要使用系统变量,系统变量时用来控制服务器的表现的,如:auto_commit. 查看系统变量 ...
- 虚拟机下Redhat9 网络配置问题(转)
原文链接:http://www.programgo.com/article/38031929690/ edhat 9/redhat as 3装在虚拟机vmware上之后,连接网络是出现问题 Deter ...
- CString与输入输出流对象问题。
在C++ 编程出现:cin>>Id;没有与这些操作匹配的">>"运算符: 你要看你的Id的数据类型,如果是CString等字符串,要用cin.getline ...
- mysql 数据传输报错 MySQL server has gone away With statement:
利用navicat premium 拷贝数据库时,报错MySQL server has gone away With statement:, 造成这样的原因一般是sql操作的时间过长,或者是传送的数据 ...
- IE11降级到IE8