美文网首页
设计模式之禅-责任链模式

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

作者: 凉快先生 | 来源:发表于2020-12-30 22:52 被阅读0次

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

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

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

    }

}

运行结果如下:

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

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

丈夫的答复是:同意

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

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

父亲的答复是:同意

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

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

儿子的答复是:同意

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

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

丈夫的答复是:同意

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

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

儿子的答复是:同意

是责任链模式通用类图:

相关文章

网友评论

      本文标题:设计模式之禅-责任链模式

      本文链接:https://www.haomeiwen.com/subject/uxvkoktx.html