当前位置:网站首页>Yesterday, Alibaba senior wrote a responsibility chain model, and there were countless bugs
Yesterday, Alibaba senior wrote a responsibility chain model, and there were countless bugs
2022-07-02 18:41:00 【InfoQ】
background
What is the chain of responsibility

Use scenarios
- Multi conditional process judgment : Access control
- ERP System process approval : The general manager 、 Personnel manager 、 project manager
- Java The underlying implementation of the filter Filter
| Counter example
- The game has a total of 3 A level
- Entering the second level requires the game score of the first level to be greater than or equal to 80
- Entering the third level requires the game score of the second level to be greater than or equal to 90
// The first level
public class FirstPassHandler {
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
return 80;
}
}
// The second level
public class SecondPassHandler {
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
return 90;
}
}
// The third level
public class ThirdPassHandler {
public int handler(){
System.out.println(" The third level -->ThirdPassHandler, This is the last level ");
return 95;
}
}
// client
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
int firstScore = firstPassHandler.handler();
// The score of the first level is greater than or equal to 80 Then enter the second level
if(firstScore >= 80){
int secondScore = secondPassHandler.handler();
// The score of the second level is greater than or equal to 90 Then enter the second level
if(secondScore >= 90){
thirdPassHandler.handler();
}
}
}
}
if( The first 1 Pass off ){
// The first 2 Turn off game
if( The first 2 Pass off ){
// The first 3 Turn off game
if( The first 3 Pass off ){
// The first 4 Turn off game
if( The first 4 Pass off ){
// The first 5 Turn off game
if( The first 5 Pass off ){
// The first 6 Turn off game
if( The first 6 Pass off ){
//...
}
}
}
}
}
}
| Preliminary modification
public class FirstPassHandler {
/**
* The next level of the first level is The second level
*/
private SecondPassHandler secondPassHandler;
public void setSecondPassHandler(SecondPassHandler secondPassHandler) {
this.secondPassHandler = secondPassHandler;
}
// Score in this level game
private int play(){
return 80;
}
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
if(play() >= 80){
// fraction >=80 And the next level exists before entering the next level
if(this.secondPassHandler != null){
return this.secondPassHandler.handler();
}
}
return 80;
}
}
public class SecondPassHandler {
/**
* The next level of the second level is The third level
*/
private ThirdPassHandler thirdPassHandler;
public void setThirdPassHandler(ThirdPassHandler thirdPassHandler) {
this.thirdPassHandler = thirdPassHandler;
}
// Score in this level game
private int play(){
return 90;
}
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
if(play() >= 90){
// fraction >=90 And the next level exists before entering the next level
if(this.thirdPassHandler != null){
return this.thirdPassHandler.handler();
}
}
return 90;
}
}
public class ThirdPassHandler {
// Score in this level game
private int play(){
return 95;
}
/**
* This is the last pass , So there's no next level
*/
public int handler(){
System.out.println(" The third level -->ThirdPassHandler, This is the last level ");
return play();
}
}
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
firstPassHandler.setSecondPassHandler(secondPassHandler);// The next level of the first level is the second level
secondPassHandler.setThirdPassHandler(thirdPassHandler);// The next level of the second level is the third level
// explain : Because the third level is the last level , So there's no next level
// Start calling the first level Whether each level enters the next level Judge in each level
firstPassHandler.handler();
}
}
| shortcoming
- Each level has a member variable of the next level and is different , It's inconvenient to form a chain
- The extensibility of the code is very bad
| Responsibility chain transformation
- Abstract processor (Handler) role : Define an interface to process requests , Contains abstract processing methods and a subsequent connection .
- Specific handler (Concrete Handler) role : Implement the processing methods of the abstract processor , Determine whether the request can be processed , If the request can be processed, process , Otherwise, forward the request to its successor .
- Customer class (Client) role : Create a processing chain , And submit the request to the specific handler object of the chain head , It doesn't care about processing details and the delivery of requests .

public abstract class AbstractHandler {
/**
* The next level uses the current abstract class to receive
*/
protected AbstractHandler next;
public void setNext(AbstractHandler next) {
this.next = next;
}
public abstract int handler();
}
public class FirstPassHandler extends AbstractHandler{
private int play(){
return 80;
}
@Override
public int handler(){
System.out.println(" The first level -->FirstPassHandler");
int score = play();
if(score >= 80){
// fraction >=80 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class SecondPassHandler extends AbstractHandler{
private int play(){
return 90;
}
public int handler(){
System.out.println(" The second level -->SecondPassHandler");
int score = play();
if(score >= 90){
// fraction >=90 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class ThirdPassHandler extends AbstractHandler{
private int play(){
return 95;
}
public int handler(){
System.out.println(" The third level -->ThirdPassHandler");
int score = play();
if(score >= 95){
// fraction >=95 And the next level exists before entering the next level
if(this.next != null){
return this.next.handler();
}
}
return score;
}
}
public class HandlerClient {
public static void main(String[] args) {
FirstPassHandler firstPassHandler = new FirstPassHandler();// The first level
SecondPassHandler secondPassHandler = new SecondPassHandler();// The second level
ThirdPassHandler thirdPassHandler = new ThirdPassHandler();// The third level
// Compared with the unchanged client code above , Only here set Method changes , Everything else is the same
firstPassHandler.setNext(secondPassHandler);// The next level of the first level is the second level
secondPassHandler.setNext(thirdPassHandler);// The next level of the second level is the third level
// explain : Because the third level is the last level , So there's no next level
// Start at the first level
firstPassHandler.handler();
}
}
| Chain of responsibility factory transformation

public enum GatewayEnum {
// handlerId, Interceptor name , Fully qualified class name ,preHandlerId,nextHandlerId
API_HANDLER(new GatewayEntity(1, "api Interface current limiting ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.ApiLimitGatewayHandler", null, 2)),
BLACKLIST_HANDLER(new GatewayEntity(2, " black block ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.BlacklistGatewayHandler", 1, 3)),
SESSION_HANDLER(new GatewayEntity(3, " User session interception ", "cn.dgut.design.chain_of_responsibility.GateWay.impl.SessionGatewayHandler", 2, null)),
;
GatewayEntity gatewayEntity;
public GatewayEntity getGatewayEntity() {
return gatewayEntity;
}
GatewayEnum(GatewayEntity gatewayEntity) {
this.gatewayEntity = gatewayEntity;
}
}
public class GatewayEntity {
private String name;
private String conference;
private Integer handlerId;
private Integer preHandlerId;
private Integer nextHandlerId;
}
public interface GatewayDao {
/**
* according to handlerId Get configuration items
* @param handlerId
* @return
*/
GatewayEntity getGatewayEntity(Integer handlerId);
/**
* Get the first handler
* @return
*/
GatewayEntity getFirstGatewayEntity();
}
public class GatewayImpl implements GatewayDao {
/**
* initialization , The configured in the enumeration handler Initialize to map in , Easy access
*/
private static Map<Integer, GatewayEntity> gatewayEntityMap = new HashMap<>();
static {
GatewayEnum[] values = GatewayEnum.values();
for (GatewayEnum value : values) {
GatewayEntity gatewayEntity = value.getGatewayEntity();
gatewayEntityMap.put(gatewayEntity.getHandlerId(), gatewayEntity);
}
}
@Override
public GatewayEntity getGatewayEntity(Integer handlerId) {
return gatewayEntityMap.get(handlerId);
}
@Override
public GatewayEntity getFirstGatewayEntity() {
for (Map.Entry<Integer, GatewayEntity> entry : gatewayEntityMap.entrySet()) {
GatewayEntity value = entry.getValue();
// There is no last one handler Is the first
if (value.getPreHandlerId() == null) {
return value;
}
}
return null;
}
}
public class GatewayHandlerEnumFactory {
private static GatewayDao gatewayDao = new GatewayImpl();
// Provide static methods , Get the first one handler
public static GatewayHandler getFirstGatewayHandler() {
GatewayEntity firstGatewayEntity = gatewayDao.getFirstGatewayEntity();
GatewayHandler firstGatewayHandler = newGatewayHandler(firstGatewayEntity);
if (firstGatewayHandler == null) {
return null;
}
GatewayEntity tempGatewayEntity = firstGatewayEntity;
Integer nextHandlerId = null;
GatewayHandler tempGatewayHandler = firstGatewayHandler;
// Iterate through all handler, And link them
while ((nextHandlerId = tempGatewayEntity.getNextHandlerId()) != null) {
GatewayEntity gatewayEntity = gatewayDao.getGatewayEntity(nextHandlerId);
GatewayHandler gatewayHandler = newGatewayHandler(gatewayEntity);
tempGatewayHandler.setNext(gatewayHandler);
tempGatewayHandler = gatewayHandler;
tempGatewayEntity = gatewayEntity;
}
// Return to the first handler
return firstGatewayHandler;
}
/**
* Reflection materializes the specific handler
* @param firstGatewayEntity
* @return
*/
private static GatewayHandler newGatewayHandler(GatewayEntity firstGatewayEntity) {
// Gets the fully qualified class name
String className = firstGatewayEntity.getConference();
try {
// According to the fully qualified class name , Load and initialize the class , The static segment of this class will be initialized
Class<?> clazz = Class.forName(className);
return (GatewayHandler) clazz.newInstance();
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
e.printStackTrace();
}
return null;
}
}
public class GetewayClient {
public static void main(String[] args) {
GetewayHandler firstGetewayHandler = GetewayHandlerEnumFactory.getFirstGetewayHandler();
firstGetewayHandler.service();
}
}
Conclusion
边栏推荐
- Troubleshooting ideas that can solve 80% of faults
- 微信小程序视频分享平台系统毕业设计毕设(2)小程序功能
- MySQL 关于 only_full_group_by 限制
- 300+ documents! This article explains the latest progress of multimodal learning based on transformer
- Interview, about thread pool
- What is cloud primordial? This time, I can finally understand!
- exness深度好文:动性系列-黄金流动性实例分析(五)
- Leetcode 面试题 16.15. 珠玑妙算
- C # detect whether the picture is rotated and modified to the true rotation
- 怎么用ps提取图片颜色分析色彩搭配
猜你喜欢
Pit encountered during installation of laravel frame
Please, stop painting star! This has nothing to do with patriotism!
Unity learning shader notes [82] black and white processing of enhanced single channel color rendering
Wechat nucleic acid detection appointment applet system graduation design completion (4) opening report
Wechat applet video sharing platform system graduation design completion (8) graduation design thesis template
Web版3D可视化工具,程序员应该知道的97件事,AI前沿论文 | 资讯日报 #2022.07.01
Ue4 dessine un cercle avec une ligne de contour
Unity学习shader笔记[八十二]增强单通道颜色渲染的黑白处理
昨天阿里学长写了一个责任链模式,竟然出现了无数个bug
Another double non reform exam 408, will it be cold? Software College of Nanchang Aviation University
随机推荐
Meal card hdu2546
如何设置VSCode删除整行快捷键?
夜神模擬器+Fiddler抓包測試App
Wechat nucleic acid detection appointment applet system graduation design (2) applet function
Ue4 dessine un cercle avec une ligne de contour
微信核酸检测预约小程序系统毕业设计毕设(2)小程序功能
Steamos 3.3 beta release, steam deck Chinese keyboard finally came
Another double non reform exam 408, will it be cold? Software College of Nanchang Aviation University
The official docker image running container in version 1.5.1 can be set to use MySQL 8 driver?
Détends - toi encore! Ces nouveaux étudiants peuvent s'installer directement à Shanghai
Win10 uninstall CUDA
Radian to angle, angle to radian in MATLAB
iptable端口重定向 MASQUERADE[通俗易懂]
Vi/vim delete: one line, one character, word, the first character of each line command
Matlab中弧度转角度、角度转弧度
夜神模拟器+Fiddler抓包测试App
科技公司不同人对Bug的反应 | 每日趣闻
Three methods of MySQL backup
Pit encountered during installation of laravel frame
SAP S/4HANA OData Mock Service 介绍