一、行为型模式
1.1、责任链模式
1.1.1、概述
为了避免请求发送者和多个请求处理者耦合在一起,就将所有请求处理者通过前一个对象记住下一个对象的引用的方式形成一条链;当有请求到来时,可以将请求沿着这条链传递,知道有对象能处理他为止.
例如,公司员工请假,可以批假的领导有小组组长、部门经理、总经理,但是每个领导比准的天数不同,那么员工请假时,就需要记住每一个领导的能请假的天数,十分不方便,但是通过责任链模式,你就可以直接把假条先交给能处理天数最少的人即可,如果小组组长处理不了,小组组长因为持有 部门经理 的引用,就可以找到他,让他处理..... 以此类推,直到找到能处理这个假条的领导为止.
责任链模式主要包含以下角色:
- 抽象处理者:定义一个处理请求的接口,包含抽象处理方法并持有下一个处理者的引用.
- 具体处理者:实现抽象处理者的处理方法,判断当前处理者能否处理请求,如果可以就处理,不可以就交给下一个处理者处理.(例如上述的,小组组长、部门经理、总经理)
- 客户类:创建处理链,并向链头的具体处理者对象提交请求,他不关心具体的处理细节和请求的传递过程.
1.1.2、案例实现
实现上述案例.
/**
* 请假条类
*/
public class LeaveRequest {
//请假人姓名
private String name;
//请假天数
private int num;
//请假原因
private String reason;
public LeaveRequest(String name, int num, String reason) {
= name;
this.num = num;
this.reason = reason;
}
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
}
/**
* 抽象处理者
*/
public abstract class Handler {
//请假天数
protected static final int ONE_DAY = 1;
protected static final int THREE_DAY = 3;
protected static final int SEVEN_DAY = 7;
//各级领导能处理请假天数区间
private int numStart;
private int numEnd;
//领导的领导
private Handler nextHandler;
/**
* 领导处理请假天数区间
* @param numStart
* @param numEnd
*/
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 request) {
if(request.getNum() <= numEnd) {
this.handlerLeave(request);
} else if(this.nextHandler != null) {
nextHandler.submit(request);
} else {
System.out.println("请假天数超过上限!");
}
}
protected abstract void handlerLeave(LeaveRequest request);
}
/**
* 具体处理者: 小组组长
*/
public class GroupLeader extends Handler {
/**
* 小组长所能处理的请假天数区间
*/
public GroupLeader() {
super(0, ONE_DAY);
}
@Override
protected void handlerLeave(LeaveRequest request) {
System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
request.getReason());
System.out.println("小组长审批通过");
}
}
/**
* 具体处理者: 部门经理
*/
public class Manager extends Handler {
/**
* 经理所能处理的请假天数区间
*/
public Manager() {
super(ONE_DAY, THREE_DAY);
}
@Override
protected void handlerLeave(LeaveRequest request) {
System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
request.getReason());
System.out.println("部门经理审批通过");
}
}
/**
* 具体处理者: 总经理
*/
public class GeneralManager extends Handler {
/**
* 经理所能处理的请假天数区间
*/
public GeneralManager() {
super(THREE_DAY, SEVEN_DAY);
}
@Override
protected void handlerLeave(LeaveRequest request) {
System.out.println(request.getName() + "请假 " + request.getNum() + " 天," +
request.getReason());
System.out.println("总经理审批通过");
}
}
/**
* 客户类
*/
public class Client {
public static void main(String[] args) {
//1.假条
LeaveRequest request1 = new LeaveRequest("李白", 1, "这几天要出诗集~");
LeaveRequest request2 = new LeaveRequest("杜甫", 3, "生病了,身体不适~");
LeaveRequest request3 = new LeaveRequest("龙洋静", 6, "着急结婚!");
//2.责任链关系
GroupLeader groupLeader = new GroupLeader();
Manager manager = new Manager();
GeneralManager generalManager = new GeneralManager();
groupLeader.setNextHandler(manager);
manager.setNextHandler(generalManager);
//3.提交假条
groupLeader.submit(request1);
System.out.println("===============");
groupLeader.submit(request2);
System.out.println("===============");
groupLeader.submit(request3);
}
}
执行结果如下:
1.1.3、优缺点
优点:
- 解耦合:降低了发送请求者和处理请求者的耦合度.
- 满足开闭原则:可以根据业务需求,新增请求处理类.
- 增强了对象指派责任的灵活性:当工作流程发生变化,可以动态的改变链内成员或者修改他们的次序,也可以动态的新增和删除责任.
- 简化了对象链接:一个对象只需要持有下一个后继者的引用,不需要保持其他所有处理者的引用,避免了众多的 if else 语句.
- 满足单一职责:每个类只需要处理自己的工作,不能处理就交给下一个对象完成.
缺点:
不能保证每一个请求一定被处理:因为请求没有明确的接收者,因此不能保证他一定被处理,该请求可能传到链末也得不到处理.
性能影响:如果责任链较长,请求的处理可能涉及到多个对象,性能会有所损耗.
复杂度:责任链的合理性全靠客户端来保证,增加了客户端的复杂度.
1.1.4、使用场景
1. 多个对象可以处理同一个请求,但具体由哪个对象处理则在运行时动态决定.
2. 请求者不明确要对哪一个对象进行提交申请.
例如像公司职级审批流的设定.
例如用户找回密码需要一步步校验的密保信息.