记得上次面试,先笔试后面试,面试官让我手写责任链模式,一脸蒙蔽 ,啥是责任链模式?于是碰壁之后,回去理了理责任链是什么东东。
1 定义:
责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推(菜鸟)。避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
2 角色
Handler: 抽象处理类,抽象处理类中主要包含一个指向下一处理类的成员变量nextHandler和一个处理请求的方法handRequest,handRequest方法的主要主要思想是,如果满足处理的条件,则有本处理类来进行处理,否则由nextHandler来处理。
ConcreteHandler: 具体处理类主要是对具体的处理逻辑和处理的适用条件进行实现。具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
Client:客户端
是不是读完行话有点蒙蔽,没有关系,我读完也蒙蒙的,我于是就百度,自己写了一个demo ,然后 大致就能掌握这种设计模式的思想了。
设计一个场景,洗车套餐 分为 1,2,3。 分别对应具体的洗车处理逻辑,请求套餐,如果是1套餐则执行,不是则传递给2套餐,如此形成链,沿着这条链传递请求,直到有对象处理它为止。
3 代码实现
3.1 抽象套餐类 包含(nextHandler ,handRequest);
package com.example.demo.responsibilityChain;
/**
* 抽象套餐类
*/
public abstract class WashCarPackage {
protected WashCarPackage nextPackage;
// 责任链下个节点
public void setNextWashCarBiz(WashCarPackage next) {
this.nextPackage = next;
}
/**
* 处理请求的核心的业务方法
*
* @param req
*/
public abstract void handleRequest(WashCarBizReq req);
}
3.2 具体套餐类()
package com.example.demo.responsibilityChain;
import lombok.extern.slf4j.Slf4j;
/** 1套餐
* @author qiangqiang
*/
@Slf4j
public class WashOneCar extends WashCarPackage {
@Override
public void handleRequest(WashCarBizReq req) {
if (req.getType().equals(washCarEnum.ONE.getCode())) {
//业务处理
log.info("washCar is {} Package ", washCarEnum.ONE.getCode());
} else {
// 创建下一个节点this.setNextWashCarBiz(WashCarHandlerChainStaticFactory.createWashTwoCar());
this.nextPackage.handleRequest(req);
}
}
}
package com.example.demo.responsibilityChain;
import lombok.extern.slf4j.Slf4j;
/**2 套餐
* @author qiangqiang
*/
@Slf4j
public class WashTwoCar extends WashCarPackage {
@Override
public void handleRequest(WashCarBizReq req) {
if (req.getType().equals(washCarEnum.TWO.getCode())) {
//业务处理
log.info("washCar is {} Package ", washCarEnum.TWO.getCode());
} else {
// 创建下一个节点 this.setNextWashCarBiz(WashCarHandlerChainStaticFactory.createWashThreeCar());
this.nextPackage.handleRequest(req);
}
}
}
package com.example.demo.responsibilityChain;
import lombok.extern.slf4j.Slf4j;
/** 3套餐
* @author qiangqiang
*/
@Slf4j
public class WashThreeCar extends WashCarPackage {
@Override
public void handleRequest(WashCarBizReq req) {
if (req.getType().equals(washCarEnum.THREE.getCode())) {
//业务处理
log.info("washCar is {} Package ", washCarEnum.THREE.getCode());
} else {
log.error("sorry ");
}
}
}
3.3 静态工厂--》创建具体套餐节点
package com.example.demo.responsibilityChain;
/**
* 静态工厂--》具体套餐
*/
public class WashCarHandlerChainStaticFactory {
public static WashOneCar createWashOneCar(){
return new WashOneCar();
}
public static WashTwoCar createWashTwoCar(){
return new WashTwoCar();
}
public static WashThreeCar createWashThreeCar(){
return new WashThreeCar();
}
}
3.4 枚举套餐
package com.example.demo.responsibilityChain;
public enum washCarEnum {
ONE("one", "1"),
TWO("two", "2"),
THREE("three", "3"),
FOUR("four", "4"),
FIVE("five", "5"),
SIX("six", "6"),
SEVEN("seven","7"),
;
/**
* 码
*/
private final String code;
/**
* 描述
*/
private final String desc;
private washCarEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public String getDesc() {
return desc;
}
public String getCode() {
return code;
}
public static String getDesc(String code) {
for (washCarEnum auditTypeEnum : values()) {
if (auditTypeEnum.getCode().equals(code)) {
return auditTypeEnum.getDesc();
}
}
return "";
}
@Override
public String toString() {
return desc;
}
}
3.5 请求参数
package com.example.demo.responsibilityChain;
import lombok.Data;
/**
* 洗车业务请求参数
*/
@Data
public class WashCarBizReq {
private String type;
private String message;
}
3.6 客户端
4,思考
写完一个demo后 我发现这个不就是 加强版的ifelse嘛? 其实责任链模式就是加强版的ifelse ,更灵活一些,看完这个demo是不是有点明白这个责任链模式了哈哈
5,用途例子
1,根据业务可以像洗车这种就可以用到。
2,try catch catch 多个的时候其实也是用到的责任链思想
3,Netty 中的 Pipeline
和 ChannelHandler
通过责任链设计模式来组织代码逻辑
4,Spring Security 使用责任链模式,可以动态地添加或删除责任(处理 request 请求)
5,Spring AOP 通过责任链模式来管理 Advisor
6,Dubbo Filter 过滤器链也是用了责任链模式(链表),可以对方法调用做一些过滤处理,譬如超时(TimeoutFilter),异常(ExceptionFilter),Token(TokenFilter)等
7,Mybatis 中的 Plugin 机制使用了责任链模式,配置各种官方或者自定义的 Plugin,与 Filter 类似,可以在执行 Sql 语句的时候做一些操作
PS :未完待续
参考:设计模式之责任链模式及典型应用
www.runoob.com
代码地址:https://github.com/coder8421/pattern.git
欢迎star