到底是不是隔壁老王?责任链模式帮小头爸爸洗绿

今天与大家谈一谈责任链模式 (Chain of Responsibility Pattern)

目的

在发送请求的类和最终处理的类之间进行解耦。

例子代码

小伙伴们都看过 大头儿子小头爸爸 么(大手牵小手, 走路不怕滑~)当初纯洁的我怎么也没想到小头爸爸的绿帽子这么鲜艳...

话说大家都这么说, 大头妈妈天天在家里生气, 小头爸爸内心也忍不住了, 于是要证明自己的清(bei)白(lv)😳

除了王叔叔, 还有二个他很怀疑的对象:尖鼻子厨师和粗眉毛保安大哥。

他现在就想看看这到底是谁的责任,这个时候他采取了如下的代码。

定义一个大头儿子类:

@Getter

publicclassBigHeadSon{

    //是否尖鼻子

privatefinalbooleanpointedNose =false;

    //是否粗眉毛

privatefinalbooleancoarseEyebrows =false;

    //是否大头

privatefinalbooleanbigHead =true;

}

定义一个决定儿子爸爸的类:

publicclassDecideFather{

    publicstaticStringfindFatherName

(BigHeadSon son){        

        if(son.isPointedNose()) {

            return"尖鼻子厨师";

       }        

        if(son.isCoarseEyebrows()) {

            return"粗眉毛保安";

       }        

        if(son.isBigHead()) {

            return"隔壁老王";

       }        

        return"小头爸爸";

}

}

然后小头爸爸试了试:

publicclassApp{

    publicstaticvoidmain(String[] args){

System.out.println(DecideFather.

findFatherName(newBigHeadSon()));

}

}

问题分析

很明显, if-else 可能无限的地方就是设计模式可以使用的地方。

这时候比如他又怀疑了卖狗狗的大胡子叔叔, 那他又要加个 if-else 了, 这个函数最终可能上百行, 变量可能共享, 那他就很难受了😫

责任链模式

先定义一套责任链的共有类:

publicinterfaceChainNode

{

R extends AbstractChainNodeRequest>

ChainResultexecute(C context, R request);

}

其中的类都是空实现, chainResult 如下:

@Data

publicclassChainResult

{

        privatebooleanprocessingCompleted;

        privateT response;

}

定义一个责任链处理器:

publicclassChainProcessor{

  publicstatic

                AbstractChainNodeResponse>        

ThandleChainNodes(List> chainNodes,

AbstractChainNodeContext context,

AbstractChainNodeRequest request,

T defaultValue)

AbstractChainNodeContext context,

AbstractChainNodeRequest request,

                  T defaultValue){

    for(ChainNode chainNode : chainNodes) {

ChainResult execute =

          chainNode.execute(context, request);            

            if(execute.isProcessingCompleted()) {

                returnexecute.getResponse();

       }

   }        

    returndefaultValue;

}

}

然后我们结合例子代码进行使用:

自定义返回值:

@Data

@NoArgsConstructor

@AllArgsConstructor

publicclassFatherNameChainNodeResponse

extendsAbstractChainNodeResponse

extendsAbstractChainNodeResponse{

    //父亲姓名

privateString fatherName;

}

使得大头儿子继承入参类:

@Getter

publicclassBigHeadSon

extendsAbstractChainNodeRequest

extendsAbstractChainNodeRequest{

    //是否尖鼻子

privatefinalbooleanpointedNose =false;

    //是否粗眉毛

privatefinalbooleancoarseEyebrows =false;

    //是否大头

privatefinalbooleanbigHead =true;

}

实现一个抽象的找爸爸类:

publicabstractclassCheckFatherChainNode

implementsChainNode{

    @Override

publicChainResult

execute(AbstractChainNodeContext context,

               AbstractChainNodeRequest request){

        returnnull;

}

}

尖鼻子检查:

publicclassNoseCheckFatherChainNode

extendsCheckFatherChainNode{

    @Override

publicChainResult

execute(AbstractChainNodeContext context,

AbstractChainNodeRequest request)

{

BigHeadSon bigHeadSon = (BigHeadSon) request;

ChainResult

chainResult =newChainResult<>();

        if(bigHeadSon.isPointedNose()) {

chainResult.setProcessingCompleted(true);

           chainResult.setResponse(            

        newFatherNameChainNodeResponse("尖鼻子厨师"));

       }        

        returnchainResult;

}

}

粗眉毛检查:

publicclassEyeBrowCheckFatherChainNode

extendsCheckFatherChainNode{

    @Override

publicChainResult

execute(AbstractChainNodeContext context,

AbstractChainNodeRequest request)

{

BigHeadSon bigHeadSon = (BigHeadSon) request;

       ChainResult<FatherNameChainNodeResponse>

        chainResult = new ChainResult<>();        

        if(bigHeadSon.isCoarseEyebrows()) {

chainResult.setProcessingCompleted(true);

           chainResult.setResponse(            

        newFatherNameChainNodeResponse("粗眉毛保安"));

       }        

        returnchainResult;

}

}

大头检查:

publicclassHeadCheckFatherChainNode

extendsCheckFatherChainNode{

    @Override

publicChainResult

execute(AbstractChainNodeContext context,

AbstractChainNodeRequest request)

{

BigHeadSon bigHeadSon = (BigHeadSon) request;

       ChainResult<FatherNameChainNodeResponse>

        chainResult = new ChainResult<>();        

        if(bigHeadSon.isBigHead()) {

chainResult.setProcessingCompleted(true);

           chainResult.setResponse(            

        newFatherNameChainNodeResponse("隔壁老王"));

       }        

        returnchainResult;

}

}

最终使用:

publicclassApp{

    publicstaticvoidmain(String[] args){

       System.out.println(ChainProcessor

       .handleChainNodes(

        Arrays.asList(

        newNoseCheckFatherChainNode(),

newEyeBrowCheckFatherChainNode(),

        newHeadCheckFatherChainNode()),

        null,

        newBigHeadSon(),

    newFatherNameChainNodeResponse("小头爸爸")));

}

}

一顿操作猛如虎, 一看还是带绿帽......

责任链课后作业

1. 结合 bean 声明学习在 Spring boot 中优雅使用责任链模式

2. 学习使用 Apache Commons Chain 包

3. 作为一个银行开发人员, 我们有个支用请求, 需要验证支用币种是否是CNY(人民币),用户是否在黑名单,是否是实名认证的用户,支用的产品是否可用,支用金额是否充足等, 请使用责任链模式完成

提供了如下入参:

@DatapublicclassLendRequest{

    //支用金额

privateString loanAmt;

    //支用币种

privateString currency;

    //支用产品

privateString pdCode;

    //用户唯一标识

privateString userId;

}

提供的接口如下:

public class Client {

//是否不在黑名单

public static boolean isNotInBlack(String userId) {

return true;

}

//是否是实名认证用户

public static boolean isRealUser(String userId) {

return true;

}

//是否产品可用

public static boolean isPdUsable(String pdCode) {

return true;

}

//是否用户额度充足

   public static boolean

    isHasSoMuchMoney(String userId, String loanAmt) {

return false;

}

}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。