责任链模式

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、夫
死从子”。也就是说,一位女性在结婚之前要听从于父亲,结婚之后要听从于丈夫,如果丈
夫死了还要听从于儿子。举例来说,如果一位女性要出去逛街,在她出嫁前必须征得父亲的
同意,出嫁之后必须获得丈夫的许可,那丈夫死了怎么办?那就得问问儿子是否允许自己出
去逛街。估计你接下来马上要问:“要是没有儿子怎么办?”那就请示小叔子、侄子等。在父
系社会中,妇女只占从属地位,现在想想中国古代的妇女还是挺悲惨的,连逛街都要多番请
示。作为父亲、丈夫或儿子,只有两种选择:要不承担起责任来,允许她或不允许她逛街;
要不就让她请示下一个人,这是整个社会体系的约束,应用到我们项目中就是业务规则。下
面来看如何通过程序来实现“三从”,需求很简单:通过程序描述一下古代妇女的“三从”制
度。好,我们先来看类图,如图

责任链模式

类图非常简单,IHandler是三个有决策权对象的接口,IWomen是女性的代码,其实现也
非常简单

package ZeRenLianP;

public interface IWomen {
    /**
     * 一个是取得当前的个人状况getType,通过返回值决定是结婚了还
     是没结婚、丈夫是否在世等
     * @return
     */
    public int getType();

    /**
     * 方法getRequest是要请示的内容,要出去逛街还是吃
     饭
     * @return
     */
    public String getRequest();
}
package ZeRenLianP;

public class Women implements IWomen {
    /**
     * 通过一个int类型的参数来描述妇女的个人状况
     * 1--未出嫁
     * 2--出嫁
     * 3--夫死
     * @return
     */
    private int type = 0;
    private String request = "";

    public Women(int type,String request){
        this.type = type;
        this.request = request;
    }
    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }
}
package ZeRenLianP;

public interface IHandler {
    public void HandleMessage(Women women);
}
package ZeRenLianP;

public class Father implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("女儿的请示是:"+women.getRequest());
        System.out.println("父亲的答复是:同意");
    }
}
package ZeRenLianP;

public class Husband implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("妻子的请示是:"+women.getRequest());
        System.out.println("丈夫的答复是:同意");
    }
}
package ZeRenLianP;

public class Son implements IHandler {
    @Override
    public void HandleMessage(Women women) {
        System.out.println("母亲的请示是:"+women.getRequest());
        System.out.println("儿子的答复是:同意");
    }
}
package ZeRenLianP;

import java.util.ArrayList;
import java.util.Random;

public class Client {
    public static void main(String[] args) {
        Random random = new Random();
        ArrayList<Women> womenArrayList =new ArrayList<>();
        for (int i = 0; i<5 ; i++){
            womenArrayList.add(new Women(random.nextInt(4),"guangjie"));
        }
        IHandler father = new Father();
        IHandler husband = new Husband();
        IHandler son = new Son();
        for (Women women:womenArrayList){
            if(women.getType() ==1){ //未结婚少女,请示父亲
                System.out.println("\n--------女儿向父亲请示-------");
                father.HandleMessage(women);
            }else if(women.getType() ==2){ //已婚少妇,请示丈夫
                System.out.println("\n--------妻子向丈夫请示-------");
                husband.HandleMessage(women);
            }else if(women.getType() == 3){ //母亲请示儿子
                System.out.println("\n--------母亲向儿子请示-------");
                son.HandleMessage(women);
            }else{
//暂时什么也不做
            }
        }
    }
}

代码有以下几个问题:
● 职责界定不清晰
对女儿提出的请示,应该在父亲类中做出决定,父亲有责任、有义务处理女儿的请示,
因此Father类应该是知道女儿的请求自己处理,而不是在Client类中进行组装出来,也就是说
原本应该是父亲这个类做的事情抛给了其他类进行处理,不应该是这样的。
● 代码臃肿
我们在Client类中写了if...else的判断条件,而且能随着能处理该类型的请示人员越
多,if...else的判断就越多,想想看,臃肿的条件判断还怎么有可读性?!
● 耦合过重
这是什么意思呢,我们要根据Women的type来决定使用IHandler的那个实现类来处理请
求。有一个问题是:如果IHandler的实现类继续扩展怎么办?修改Client类?与开闭原则违背
了!
● 异常情况欠考虑
妻子只能向丈夫请示吗?如果妻子(比如一个现代女性穿越到古代了,不懂什么“三从
四德”)向自己的父亲请示了,父亲应该做何处理?我们的程序上可没有体现出来,逻辑失
败了!

可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就
作出回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去
天国报道了,那就由儿子来处理这个请求。

责任链模式

package ZeRenLianP;

public abstract class Handle {
    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 Handle nextHandler;
    //每个类都要说明一下自己能处理哪些请求
    public Handle(int _level){
        this.level = _level;
    }

//一个女性(女儿、妻子或者是母亲)要求逛街,你要处理这个请求
    public final void HandleMessage(Women women){
        if (women.getType() == this.level){
            this.response(women);
        }else {
            if (this.nextHandler != null){
                this.nextHandler.HandleMessage(women);
            }else {
                System.out.println("没有人了,不同意");
            }
        }
    }

    /**
     * 如果不属于你处理的请求,你应该让她找下一个环节的人,如女儿出嫁了,
     * 还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
     * @param
     */
    public void setNext(Handle handle){
        this.nextHandler = handle;
    }
    protected abstract void response(IWomen w);
}
package ZeRenLianP;

public class Father extends Handle {
    public Father(){
        super(Handle.FATHER_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------女儿向父亲请示-------");
        System.out.println(women.getRequest());
        System.out.println("父亲的答复是:同意\n");
    }
}
package ZeRenLianP;

public class Husband extends Handle {
    public Husband(){
        super(Handle.HUSBAND_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------妻子向丈夫请示-------");
        System.out.println(women.getRequest());
        System.out.println("丈夫的答复是:同意\n");
    }
}
package ZeRenLianP;

public class Son extends Handle {
    public Son(){
        super(Handle.SON_LEVEL_REQUEST);
    }
    @Override
    protected void response(IWomen women) {
        System.out.println("--------母亲向儿子请示-------");
        System.out.println(women.getRequest());
        System.out.println("儿子的答复是:同意\n");
    }
}
package ZeRenLianP;

public class Women implements IWomen {
    /**
     * 通过一个int类型的参数来描述妇女的个人状况
     * 1--未出嫁
     * 2--出嫁
     * 3--夫死
     * @return
     */
    private int type = 0;
    private String request = "";

    public Women(int type,String request){
        this.type = type;
        //this.request = request;
        switch (type){
            case 1:
                this.request = "女儿的请求是:" + request;
                break;
            case 2:
                this.request = "妻子的请求是:" + request;
                break;
            case 3:
                this.request = "母亲的请求是:" + request;
        }

    }
    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }
}
package ZeRenLianP;

import java.util.ArrayList;
import java.util.Random;

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

责任链模式定义如下:
Avoid coupling the sender of a request to its receiver by giving more than one object a chance to
handle the request.Chain the receiving objects and pass the request along the chain until an object
handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关
系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。)

抽象的处理者实现三个职责:一是定义一个请求的处理方法handleMessage,唯一对外开
放的方法;二是定义一个链的编排方法setNext,设置下一个处理者;三是定义了具体的请求
者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务echo。