java设计模式之责任链模式

本文以中国古代女性外出逛街的场景为例,介绍了责任链模式的设计思想及其具体实现方式。通过定义一个处理请求的对象链,使得多个处理者能够负责同一请求,提高了系统的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

故事从”三从四德”说起

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、夫死从子”。现在我们模拟一个场景:如果一位女性要出去逛街,首先她必须征得父亲的同意,如果没有父亲就必须请求丈夫,那丈夫死了怎么办?那就得问问儿子是否允许自己出去逛街。顺序处理图如下:

父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回应;要么把请求交给下一个处理者处理。结构分析得已经很清楚了,那我们看怎么来实现这个功能,类图如下:

Handler类的实现

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;
    }
    //一个女性(女儿、妻子或者是母亲)要求逛街,你要处理这个请求
    public final void HandleMessage(IWomen women){
        if(women.getType() == this.level){
            this.response(women);
        }else{
            if(this.nextHandler != null){   //有后续环节,才把请求往后递送
                this.nextHandler.HandleMessage(women);
            }else{ //已经没有后续处理人了,不用处理了
                System.out.println("---没地方请示了,按不同意处理---\n");
            }
        }
    }
    /*
    * 如果不属于你处理的请求,你应该让她找下一个环节的人,如女儿出嫁了,
    * 还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
    */
    public void setNext(Handler _handler){
        this.nextHandler = _handler;
    }
    //有请示那当然要回应
    protected abstract void response(IWomen women);
}

父亲类

public class Father extends Handler {
    //父亲只处理女儿的请求
    public Father(){
        super(Handler.FATHER_LEVEL_REQUEST);
    }
    //父亲的答复
    protected void response(IWomen women) { 
        System.out.println("女儿向父亲请示:"+women.getRequest()); System.out.println("父亲的答复是:同意\n");
    }
}

丈夫类

public class Husband extends Handler {
    //丈夫只处理妻子的请求
    public Husband(){

        super(Handler.HUSBAND_LEVEL_REQUEST);
    }
    //丈夫请示的答复
    protected void response(IWomen women) {
        System.out.println("妻子向丈夫请示:"+women.getRequest()); System.out.println("丈夫的答复是:同意\n");
    }
}

儿子类

public class Son extends Handler {
    //儿子只处理母亲的请求
    public Son(){
        super(Handler.SON_LEVEL_REQUEST);
    }
    //儿子的答复
    protected void response(IWomen women) { 
        System.out.println("母亲向儿子请示:"+women.getRequest()); System.out.println("儿子的答复是:同意\n");
    }
}

这三个类都很简单,构造方法是必须实现的,父类框定子类必须有一个显式构造函数,子类不实现编译不通过。通过构造方法我们设置了各个类能处理的请求类型,Father只能处 理请求类型为1(也就是女儿)的请求;Husband只能处理请求类型类为2(也就是妻子)的 请求,儿子只能处理请求类型为3(也就是母亲)的请求,那如果请求类型为4的该如何处理呢?在Handler中我们已经判断了,如何没有相应的处理者(也就是没有下一环节),则视为不同意。

女性接口

public interface IWomen {
    //获得个人状况
    public int getType();
    //获得个人请示,你要干什么?出去逛街?约会?还是看电影?
    public String getRequest();
}

女性类

public class Women implements IWomen{
    /*
    * 通过一个int类型的参数来描述妇女的个人状况

    * 1--未出嫁
    * 2--出嫁
    * 3--夫死
    */
    private int type=0;
    //妇女的请示
    private String request = "";
    //构造函数传递过来请求
    public Women(int _type,String _request){
    this.type = _type;
    this.request   = _request;
    }


    //获得自己的状况
    public int getType(){
        return this.type;
    }
    //获得妇女的请求
    public String getRequest(){
        return this.request;
    }
}

我们再来看Client类是怎么描述古代这一个礼节的,

场景类如下

public class Client {
    public static void main(String[] args) {
        //随机挑选几个女性
        Random rand = new Random();
        ArrayList<IWomen> arrayList = new ArrayList();
        for(int i=0;i<5;i++){
            arrayList.add(new Women(rand.nextInt(4),"我要出去逛街"));
        }
        //定义三个请示对象
        Handler father = new Father();
        Handler husband = new Husband();
        Handler son = new Son();
        //设置请示顺序
        father.setNext(husband);
        husband.setNext(son);
        for(IWomen women:arrayList){
            father.HandleMessage(women);
        }
    }
}

在Client中设置请求的传递顺序,先向父亲请示,不是父亲应该解决的问题,则由父亲

传递到丈夫类解决,若不是丈夫类解决的问题则传递到儿子类解决,最终的结果必然有一个 返回,其运行结果如下所示。

--------妻子向丈夫请示------- 妻子的请求是:我要出去逛街 丈夫的答复是:同意
--------女儿向父亲请示------- 女儿的请求是:我要出去逛街 父亲的答复是:同意
--------母亲向儿子请示------- 母亲的请求是:我要出去逛街 儿子的答复是:同意
--------妻子向丈夫请示------- 妻子的请求是:我要出去逛街 丈夫的答复是:同意
--------母亲向儿子请示------- 母亲的请求是:我要出去逛街 儿子的答复是:同意

结果也正确,业务调用类Client也不用去做判断到底是需要谁去处理,而且Handler抽象 类的子类可以继续增加下去,只需要扩展传递链而已,调用类可以不用了解变化过程,甚至是谁在处理这个请求都不用知道。

责任链模式的优点

责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处 理者可以不用知道请求的全貌(例如在J2EE项目开发中,可以剥离出无状态Bean由责任链处 理),两者解耦,提高系统的灵活性。

责任链模式的缺点

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

责任链模式的注意事项

链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。

代码链接:http://download.youkuaiyun.com/detail/mffandxx/9511399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序编织梦想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值