目录
结构
职责链模式主要包含以下角色:
-
抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
-
具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
-
客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
案例
审批假条:实例说明 某OA系统需要提供一个假条审批的模块,如果员工请假天数小于3天,主任可以审批该假条;如果员工请假天数大于等于3天,小于10天,经理可以审批;如果员工请假天数大于等于10天,小于30天,总经理可以审批;如果超过30天,总经理也不能审批,提示相应的拒绝信息。
代码实现
请假条类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 请假条类
* @date: 2023/7/21 13:37
*/
public class LeaveRequest {
// 请假人姓名和请假天数
private String leaveName;
private int leaveDays;
public LeaveRequest(String leaveName, int leaveDays ){
this.leaveName = leaveName;
this.leaveDays = leaveDays;
}
public String getLeaveName() {
return leaveName;
}
public void setLeaveName(String leaveName) {
this.leaveName = leaveName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
}
抽象处理者类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 抽象处理者类
* @date: 2023/7/21 13:40
*/
public abstract class Leader {
protected Leader successor;
protected String name;
public Leader(String name){
this.name = name;
}
// 设置下一级领导
public void setSuccessor(Leader successor){
this.successor = successor;
}
// 请假条处理
public abstract void handleRequest(LeaveRequest leaveRequest);
}
具体处理者类
主任类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 主任类
* @date: 2023/7/21 13:45
*/
public class Director extends Leader{
public Director(String name){
super(name);
}
@Override
public void handleRequest(LeaveRequest leaveRequest) {
if(leaveRequest.getLeaveDays() < 3){
System.out.printf("主任 %s 批准 %s 请假 %d 天\n"
,this.name,leaveRequest.getLeaveName(),
leaveRequest.getLeaveDays());
}
else {
// 如果有上级领导,交给上级领导处理
if(this.successor != null)
{
this.successor.handleRequest(leaveRequest);
}
}
}
}
经理类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 经理类
* @date: 2023/7/21 13:55
*/
public class Manager extends Leader {
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest leaveRequest) {
int days = leaveRequest.getLeaveDays();
if(days >= 3 && days < 10){
System.out.printf("经理 %s 批准 %s 请假 %d 天\n"
,this.name,leaveRequest.getLeaveName(),
leaveRequest.getLeaveDays());
}
else {
// 如果有上级领导,交给上级领导处理
if(this.successor != null)
{
this.successor.handleRequest(leaveRequest);
}
}
}
}
总经理类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 总经理类
* @date: 2023/7/21 13:56
*/
public class GennralManager extends Leader{
public GennralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest leaveRequest) {
int days = leaveRequest.getLeaveDays();
if(days < 30){
System.out.printf("总经理 %s 批准 %s 请假 %d 天\n"
,this.name,leaveRequest.getLeaveName(),
leaveRequest.getLeaveDays());
}
else {
System.out.print("请假天数超过30天,不予请假\n");
}
}
}
测试类
package chain_of_responsibility;
/**
* @author: ZQH
* @project: Design Pattern
* @description 测试类
* @date: 2023/7/21 12:32
*/
public class Client {
public static void main(String[] args) {
// 实例化具体领导
Director director = new Director("王明");
Manager manager = new Manager("小红");
GennralManager gennralManager = new GennralManager("老蒋");
// 设置下一级领导
director.setSuccessor(manager);
manager.setSuccessor(gennralManager);
// 实例化请假条
LeaveRequest leaveRequest1 = new LeaveRequest("张三",1);
LeaveRequest leaveRequest2 = new LeaveRequest("李四",5);
LeaveRequest leaveRequest3 = new LeaveRequest("王五",15);
LeaveRequest leaveRequest4 = new LeaveRequest("赵六",40);
// 处理请假
director.handleRequest(leaveRequest1);
System.out.println("_________________");
director.handleRequest(leaveRequest2);
System.out.println("_________________");
director.handleRequest(leaveRequest3);
System.out.println("_________________");
director.handleRequest(leaveRequest4);
}
}
优缺点
优点
- 使得一个对象无须知道是其他哪一个对象处理其请求,降低了系统的耦合度 可简化对象之间的相互连接
- 给对象职责的分配带来更多的灵活性
- 增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新建链即可
缺点
- 不能保证请求一定会被处理
- 对于比较长的职责链,系统性能将受到一定影响,在进行代码调试时不太方便
- 如果建链不当,可能会造成循环调用,将导致系统陷入死循环