责任链模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
意图: 避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决: 职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用: 在处理消息的时候以过滤很多道。
如何解决: 拦截的类都实现统一接口。
关键代码: Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
应用实例:
优点:
缺点:
使用场景:
注意事项: 在 JAVA WEB 中遇到很多应用。
主要涉及到以下几个核心角色:
抽象处理者(Handler):
定义一个处理请求的接口,通常包含一个处理请求的方法(如 handleRequest)和一个指向下一个处理者的引用(后继者)。
具体处理者(ConcreteHandler):
实现了抽象处理者接口,负责处理请求。如果能够处理该请求,则直接处理;否则,将请求传递给下一个处理者。
客户端(Client):
创建处理者对象,并将它们连接成一条责任链。通常,客户端只需要将请求发送给责任链的第一个处理者,无需关心请求的具体处理过程。
代码实现
以公司中的OA申请为例,有各种申请:请假、离职、团建、加班、购买设备等;不同申请需要的权限不一样,需要审批的人不一样。
定义申请类
/**
* 申请
*/
public class Petition {
/**
* 标题
*/
private String name;
/**
* 内容
*/
private String content;
private Type type;
/**
* 申请人
*/
private String asker;
public Petition(String name, String content, String asker, Type type) {
this.name = name;
this.content = content;
this.asker = asker;
this.type = type;
}
public String getName() {
return name;
}
public String getContent() {
return content;
}
public Type getType() {
return type;
}
public String getAsker() {
return asker;
}
public enum Type {
/**
* 请假
*/
LEAVE,
/**
* 加班
*/
OVERTIME,
/**
* 离职
*/
OFF_WORK,
/**
* 团建
*/
TRAVEL,
/**
* 购买设备
*/
BUY_EQUIPMENT,
/**
* 其他
*/
OTHER
}
}
定义抽象职位
/**
* 职位
*/
public abstract class Position {
private Position nextPosition;
public Position getNextPosition() {
return this.nextPosition;
}
public Position nextPosition(Position nextPosition) {
this.nextPosition = nextPosition;
return this.nextPosition;
}
public abstract boolean handle(Petition petition);
}
定义小组长,小组长只能审批类型为其他的申请
/**
* 小组长
*/
public class TeamLeader extends Position{
@Override
public boolean handle(Petition petition) {
if (petition.getType() == Petition.Type.OTHER){
System.out.println("小组长审批" + petition.getName() + "通过");
return true;
}
//小组长没有权限,提交给上一级审批
return getNextPosition().handle(petition);
}
}
定义经理,经理能够审批加班,请假,团建的申请
/**
* 项目经理
*/
public class Manager extends Position{
@Override
public boolean handle(Petition petition) {
if (petition.getType() == Petition.Type.OVERTIME
|| petition.getType() == Petition.Type.LEAVE
|| petition.getType() == Petition.Type.TRAVEL){
System.out.println("项目经理审批" + petition.getName() + "通过");
return true;
}
//项目经理没有权限,提交给上一级审批
return getNextPosition().handle(petition);
}
}
定义总经理,能够审批购买设备,离职的申请
/**
* 总经理
*/
public class GeneralManager extends Position{
@Override
public boolean handle(Petition petition) {
if (petition.getType() == Petition.Type.BUY_EQUIPMENT
||petition.getType() == Petition.Type.OFF_WORK){
System.out.println("总经理经理审批" + petition.getName() + "通过");
return true;
}else {
System.out.println("总经理经理审批" + petition.getName() + "不通过");
return false;
}
}
}
客户端
public class Client {
public static void main(String[] args) {
Manager manager = new Manager();
TeamLeader teamLeader = new TeamLeader();
GeneralManager generalManager = new GeneralManager();
//小组长上级项目经理,项目经理上级总经理
teamLeader.nextPosition(manager).nextPosition(generalManager);
teamLeader.handle(new Petition("Buy equipment", "I need to buy a new computer", "Jim", Petition.Type.BUY_EQUIPMENT));
teamLeader.handle(new Petition("Leave", "I need to leave", "Jim", Petition.Type.LEAVE));
teamLeader.handle(new Petition("Overtime", "I need to work overtime", "Jim", Petition.Type.OVERTIME));
teamLeader.handle(new Petition("Off work", "I need to go off work", "Jim", Petition.Type.OFF_WORK));
teamLeader.handle(new Petition("Travel", "I need to travel", "Jim", Petition.Type.TRAVEL));
teamLeader.handle(new Petition("Other", "I need to do something else", "Jim", Petition.Type.OTHER));
}
}