白话设计模式之责任链模式

记得上次面试,先笔试后面试,面试官让我手写责任链模式,一脸蒙蔽 ,啥是责任链模式?于是碰壁之后,回去理了理责任链是什么东东。

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 中的 PipelineChannelHandler 通过责任链设计模式来组织代码逻辑

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

猜你喜欢

转载自blog.csdn.net/qq_34661615/article/details/107932500