设计模式之禅-责任链模式

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、 夫死从子”,在父系社会中,妇女只占从属地位,现在想想中国的妇女还是比较悲 惨的,逛个街还要请示来请示去,而且作为 父亲、丈夫、儿子 只有两种选择:要不承担起责任来告诉她允 许或不允许逛街,要不就让她请示下一个人 ,这是整个社会体 系的约束。

通过程序描述一下古代妇女的“三从 ”制度,好我们先看类图:

publicinterface IWomen { 

    //获得个人状况

    publicint getType();

    //获得个人请示,你要干什么?出去逛街?约会?还是看电影

    public String getRequest();

女性就两个参数,一个是当前的个人状况, 是结婚了呢还是没结婚,丈夫有没有去世,另外一个是要请示的内容,要出去逛街呀还是吃饭,我们看实现类:

publicclass Women implements IWomen{ 

    /*  * 通过一个int类型的参数来描述妇女的个人状况  * 1---未出嫁  * 2---出嫁  * 3---夫死  */

    privateinttype=0; 

    //妇女的请示

    private String request = "";

    //构造函数传递过来请求

    public Women(int _type,String _request){ 

        this.type = _type;

        this.request = _request;

    } 

    //获得自己的状况

    publicint getType(){

        returnthis.type;

    }

    //获得妇女的请求

    public String getRequest(){

        returnthis.request;

    }

我们再来看有处理权的人员接口:

public interface IHandler {

    //一个女性(女儿,妻子或者是母亲)要求逛街,你要处理这个请求

    public void HandleMessage(IWomen women);

}

父亲、丈夫、儿子都是这个IHandler接口的实现者:

父亲

publicclass Father implements IHandler { 

    //未出嫁女儿来请示父亲

    publicvoid HandleMessage(IWomen women) { 

        System.out. println("女儿的请示是:"+women.getRequest());

        System.out.println("父亲的答复是:同意"); 

    }

}

丈夫类

publicclass Husband implements IHandler {

    //妻子向丈夫请示

    publicvoid HandleMessage(IWomen women) { 

        System.out. println("妻子的请示是:"+women. getRequest());

        System.out. println("丈夫的答复是:同意"); 

    }

}

儿子类

publicclass Son implements IHandler { 

    //目前向儿子请示

    public void HandleMessage(IWomen women) { 

        System.out. println("母亲的请示是:"+women. getRequest());

        System.out. println("儿子的答复是:同意");

    }

}

这三个类非常非常的简单,就一个方法,处理女儿、妻子、母亲提出的请求,再来看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),"我要出去逛街"));

          } 

        //定义三个请示对象

        IHandler father = new Father(); 

        IHandler husband = new Husband(); 

        IHandler son = new Son();

        for(IWomen women:arrayList){

            if(women.getType() ==1){

                //未结婚少女,请示父亲

                System.out.println("\n--------女儿向父亲请示-------");

                 father.HandleMessage(women);

              }elseif(women.getType()==2){ 

                    //已婚少妇,请示丈夫

                    System.out.println("\n--------妻子向丈夫请示-------");

                    husband.HandleMessage(women);

               }elseif(women.getType() == 3){

                    //母亲请示儿子

                    System.out.println("\n--------母亲向儿子请示-------");

                    son.HandleMessage (women);

              }else{

                    //暂时啥也不做

              }

          }

    }

}

运行结果如下:

--------女儿向父亲请示------- 女儿的请示是:我要出去逛街

父亲的答复是:同意

--------妻子向丈夫请示------- 妻子的请示是:我要出去逛街

丈夫的答复是:同意

--------妻子向丈夫请示------- 妻子的请示是:我要出去逛街

丈夫的答复是:同意

--------女儿向父亲请示------- 女儿的请示是:我要出去逛街

父亲的答复是:同意

这段代码有以下几个问题:

失去面向对象的意义。对女儿提出的请示,应该在父亲类中做出决定,父亲这个类应该是知道女儿的请求应该自己处理,而不是在 Client 类中进行组装出来,也就是说原本应该是父亲这个类做的事情抛给了其他类进行处理;耦合过重。这个什么意思呢,我们要根据 Women 的 type 来决定使用 IHandler 的那个实现类来处理请求,我问你,如果 IHanlder 的实现类继续扩展怎么办?修改 Client 类?与开闭原则违背喽!

异常情况没有考虑。妻子只能向丈夫请示吗?如果妻子向自己的父亲请示了,父亲应该做何处理?我们的程序上可没有体现出来。

既然有这么多的问题,那我们要想办法来解决这些问题,我们可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求,类似于这样请求:


父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回复;要么把请求转发到后序环节。


三个实现类 Father、Husband、Son 只要实现构造函数和父类的中抽象方法就可以了,具体怎么处理这些请求,都已经转移到了 Hanlder 抽象类中:

public abstract class Handler {

    //能处理的级别

    private int level =0;

    //责任传递,下一个人责任人是谁

    private Handler nextHanlder;

    //每个类都要说明一下自己能处理哪些请求

    public Handler(int _level){

        this.level = _level;

    }

    //一个女性(女儿,妻子或者是母亲)要求逛街,你要处理这个请求

    public final void HandleMessage(IWomen women){

        if(women.getType() == this.level){

            this.response(women);

        }else{

            if(this.nextHanlder != null){ //有后续环节,才把请求往后递送

                this.nextHanlder.HandleMessage(women);

            }else{ //已经没有后续处理人了,不用处理了

                System.out.println("-----------没地方请示了,不做处理!---------\n");

            }

        }

    }

    /*

    * 如果你属于你处理的返回,你应该让她找下一个环节的人,比如

    * 女儿出嫁了,还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示

    */

    public void setNext(Handler _handler){

        this.nextHanlder = _handler;

    }

    //有请示那当然要回应

    public abstract void response(IWomen women);

}

其实在这里也用到模版方法模式,在模版方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应。基本方法 response 要各个实现类都要实现:

父亲:

public class Father extends Handler {

    //父亲只处理女儿的请求

    public Father(){

        super(1);

    }

    //父亲的答复

    @Override

    public void response(IWomen women) {

        System.out.println("--------女儿向父亲请示-------");

        System.out.println(women.getRequest());

        System.out.println("父亲的答复是:同意\n");

    }

}

丈夫:

public class Husband extends Handler {

    //丈夫只处理妻子的请求

    public Husband(){

        super(2);

    }

    //丈夫请示的答复

    @Override

    public void response(IWomen women) {

        System.out.println("--------妻子向丈夫请示-------");

        System.out.println(women.getRequest());

        System.out.println("丈夫的答复是:同意\n");

    }

}

儿子;

public class Son extends Handler {

    //儿子只处理母亲的请求

    public Son(){

        super(3);

    }

    //儿子的答复

    public void response(IWomen women) {

        System.out.println("--------母亲向儿子请示-------");

        System.out.println(women.getRequest());

        System.out.println("儿子的答复是:同意\n");

    }

}

Women 类的接口没有任何变化,实现类少有变化:

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;

        //为了显示好看点,我在这里做了点处理

        switch(this.type){

            case 1:

                this.request = "女儿的请求是:" + _request;

                break;

        case 2:

                this.request = "妻子的请求是:" + _request;

                break;

        case 3:

                this.request = "母亲的请求是:" + _request;

                break;

        }

    }

    //获得自己的状况

    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 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);

    }

}

运行结果如下:

--------妻子向丈夫请示-------

妻子的请求是:我要出去逛街

丈夫的答复是:同意

--------女儿向父亲请示-------

女儿的请求是:我要出去逛街

父亲的答复是:同意

--------母亲向儿子请示-------

母亲的请求是:我要出去逛街

儿子的答复是:同意

--------妻子向丈夫请示-------

妻子的请求是:我要出去逛街

丈夫的答复是:同意

--------母亲向儿子请示-------

母亲的请求是:我要出去逛街

儿子的答复是:同意

是责任链模式通用类图:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 221,695评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,569评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,130评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,648评论 1 297
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,655评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,268评论 1 309
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,835评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,740评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,286评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,375评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,505评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,185评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,873评论 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,357评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,466评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,921评论 3 376
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,515评论 2 359

推荐阅读更多精彩内容