设计模式10-责任链模式

时间:2022-06-13 07:42:12

        中国古代对妇女制定了“三从四德”的道德规范,“三从”是指未嫁从父,既嫁从夫,夫死从子。也就是说一位女性在结婚之前要听从父亲,结婚后要听从于丈夫,如果丈夫死了还要听从于儿子。比如要逛街,作为父亲,丈夫或儿子,只有两种选择:要不要承担起责任来,允许她或不允许她逛街;要不就让她请示下一个人。这就延伸出了责任链模式。类图如下:

设计模式10-责任链模式


      上面处理请求有三个实现类,Father,Husband,Son只要实现构造函数和父类中的抽象方法response方法就可以了,具体由谁处理女性提出的请求,都已转移到了Handler抽象类中。

女性接口代码如下:

package com.jack.responsibilitychain;
/**
* Created by jack on 2017/8/7.
* 女性接口
*/
public interface IWomen {
/**
*获得个人状况,通过返回值确定结婚与否,丈夫是否去世
* @return
*/
public int getType();

/**
*获得个人请示,出去逛街还是吃饭
* @return
*/
public String getRequest();
}


女性实现类代码如下:

package com.jack.responsibilitychain;/** * Created by jack on 2017/8/7. * 女性类 */public class Women implements IWomen{    /**     * 通过参数来描述妇女的个人状况     * 1---未出嫁     * 2---出嫁     * 3---夫死     */    private int type;    /**     * 妇女的请示     */    private String request = "";    /**     * 构造函数传递过来请求     * @param type     * @param request     */    public Women(int type, String request) {        this.type = type;        switch (this.type){            case 1:                this.request = "女儿的请求是:"+request;                break;            case 2:                this.request = "妻子的请求是:"+request;                break;            case 3:                this.request = "母亲的请求是:"+request;                break;        }    }    /**     * 获得妇女的个人状况     * @return     */    @Override    public int getType() {        return this.type;    }    /**     * 获得妇女的请求     * @return     */    @Override    public String getRequest() {        return this.request;    }}





下面我们看看Handler怎么实现,代码如下:

package com.jack.responsibilitychain;/** * Created by jack on 2017/8/7. * 处理抽象类 */public abstract class Handler {    /**     * 定义常量     */    public final static int FATHER_LEVEL_REQUEST = 1;    public final static int HUSBAND_LEVEL_REQUEST = 2;    public final static int SON_LEVEL_REQUEST = 3;    /**     * 能处理的级别     */    private int level = 0;    /**     * 责任传递,下一个人责任人是谁     */    private Handler nextHandler;    public Handler(int level) {        this.level = level;    }    /**     * 一个女性要求逛街或吃饭,你需要处理这个请求     * @param women     */    public final void HandleMessage(IWomen women){        if (this.level == women.getType()) {            this.response(women);        }else {            //有后续环节才把请求往后传递            if (this.nextHandler != null) {                this.nextHandler.HandleMessage(women);            }else {//已经没有后续处理人了,不用处理了                System.out.println("--没地方请示了,按不同意处理\n--");            }        }    }    /**     * 如果不属于你处理的请求,你应该让她找下一个环节的人,如果女儿出嫁了,     * 还向父亲请示能否逛街,那父亲应该告诉女儿,应该找丈夫请示     * @param handler     */    public void setNext(Handler handler){        this.nextHandler = handler;    }    /**     * 有请示还需要回应,该方法就是表示回应     * @param women     */    public abstract void response(IWomen women);}


   上面使用到了模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,有下一个环节做出回应,如果已经达到环节结尾,则直接做不同处理。基本方法response需要各个实现类实现,每个实现类只要实现两个职责:一是定义自己能够处理的级别;二是对请求做出回应。


父亲类代码:

package com.jack.responsibilitychain;/** * Created by jack on 2017/8/7.、 * 父亲类 */public class Father extends Handler{    /**     * 父亲只处理女儿的请求     */    public Father() {        super(Handler.FATHER_LEVEL_REQUEST);    }    /**     * 父亲的答复     * @param women     */    @Override    public void response(IWomen women) {        System.out.println("---------女儿向父亲请示----------");        System.out.println(women.getRequest());        System.out.println("父亲的答复是:同意\n");    }}


丈夫类:

package com.jack.responsibilitychain;/** * Created by jack on 2017/8/7. * 丈夫类 */public class Husband extends Handler{    /**     * 丈夫只处理妻子的请求     */    public Husband() {        super(Handler.HUSBAND_LEVEL_REQUEST);    }    /**     * 丈夫请示的答复     * @param women     */    @Override    public void response(IWomen women) {        System.out.println("---------妻子向丈夫请示----------");        System.out.println(women.getRequest());        System.out.println("丈夫的答复是:同意\n");    }}


儿子类:

package com.jack.responsibilitychain;/** * Created by jack on 2017/8/7. * 儿子类 */public class Son extends Handler{    /**     * 儿子只处理母亲的请求     */    public Son() {        super(Handler.SON_LEVEL_REQUEST);    }    /**     * 儿子的答复     * @param women     */    @Override    public void response(IWomen women) {        System.out.println("---------母亲向儿子请示----------");        System.out.println(women.getRequest());        System.out.println("儿子的答复是:同意\n");    }}


测试代码如下:

package com.jack.responsibilitychain;import java.util.ArrayList;import java.util.Random;/** * Created by jack on 2017/8/7. */public class MainTest7 {    public static void main(String[] args) throws CloneNotSupportedException {        //随机挑选几个女性        Random random = new Random();        ArrayList<IWomen> womenList = new ArrayList<>();        for (int i=0;i<5;i++){            womenList.add(new Women(random.nextInt(4), "我要出去逛街"));        }        //定义三个请示对象        Father father = new Father();        Husband husband = new Husband();        Son son = new Son();        //设置请示顺序        father.setNext(husband);        husband.setNext(son);        for (IWomen women: womenList) {            father.HandleMessage(women);        }    }}


测试可能的一种输出如下:

--没地方请示了,按不同意处理----没地方请示了,按不同意处理----没地方请示了,按不同意处理-----------女儿向父亲请示----------女儿的请求是:我要出去逛街父亲的答复是:同意---------妻子向丈夫请示----------妻子的请求是:我要出去逛街丈夫的答复是:同意

       责任链模式的定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

       责任链模式的重点是在链上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果,其通用类图如下:

设计模式10-责任链模式


优点:

      责任链模式非常明显的优点是将请求和处理分开。请求者可以不用知道谁处理的,处理者可以不用知道请求的全貌,两者解耦,提供系统的灵活性。


缺点:

       责任链有两个非常显著的缺点:一是性能问题,每个请求都是从链同遍历到链尾,特别是在链比较长的时候,性能时一个非常大的问题。二是调试不方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。

代码地址:https://github.com/wj903829182/springboot/tree/master/designpattern/src/main/java/com/jack/responsibilitychain