《设计模式之禅》学习之 “责任链模式”
本章一开始举了中国古代对妇女制定的 “三从四德” 的道德规范,形象地将女性在 “未嫁-> 出嫁 -> 丧父” 三个不同的状态下请示出门逛街获得的处理,未嫁的时候,请示父亲;出嫁了,请示丈夫;丈夫去世了,请示儿子。责任链就是:父亲 -> 丈夫 -> 儿子。如果出嫁了,请示父亲,会得到什么结果?答案是:父亲告诉他,你该去请示你的丈夫。读完还是蛮形象的。 其实,作者给我们阐述了这么一个场景:一个请求到来的时候,请求方并不知道也不必知道谁去处理请求,责任链也不必关心谁发出的请求。请求来了,从第一个处理者开始,如果属于这一层,就处理。不属于?分发到下一个节点。下一个不能处理怎么办?再下一个。寻找处理者就是遍历链表节点的过程。 为什么这么做?这样做,就避免了请求和处理耦合在一起,代码也简洁了很多。 Talk is cheap, show me the code. 先创建一个女性接口:
public interface IWomen { // 获得个人状态. public int getType(); // 获得个人请示 public String getRequest(); }
创建一个古代妇女:
public class Women implements IWomen { /** * 通过 int 类型的参数来描述妇女的个人状况. * <p/> * 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; } } /** * 获取自己的状态. * * @return */ public int getType() { return this.type; } /** * 获取妇女的请求. * * @return */ public String getRequest() { return this.request; } }
有处理权的人员接口:
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 (women.getType() == this.level) { this.response(women); } else { if (null != this.nextHandler) { this.nextHandler.HandleMessage(women); } else { // 没有后续的处理人了. System.out.println("\n-------没有地方请示了,按不同意处理-------\n"); } } } /** * 如果不属于该类处理的请求,应该将其设置到下一个需要请求的环节. * * @param handler */ public void setNextHandler(Handler handler) { this.nextHandler = handler; } /** * 有请求肯定要有回应 * * @param women */ protected abstract void response(IWomen women); }
父亲类:
public class Father extends Handler { public Father() { super(Handler.FATHER_LEVEL_REQUEST); } @Override protected void response(IWomen women) { System.out.println("\n-------女儿向父亲请示-------"); System.out.println(women.getRequest()); System.out.println("父亲的回答是: 同意\n"); } }
丈夫类:
public class Husband extends Handler { public Husband() { super(Handler.HUSBAND_LEVEL_REQUEST); } @Override protected void response(IWomen women) { System.out.println("-------妻子向丈夫请示-------"); System.out.println(women.getRequest()); System.out.println("丈夫的答复是: 同意"); } }
儿子类:
public class Son extends Handler { public Son() { super(Handler.SON_LEVEL_REQUEST); } @Override protected void response(IWomen women) { System.out.println("-------母亲向儿子请示-------"); System.out.println(women.getRequest()); System.out.println("儿子的答复是: 同意\n"); } }
场景类:
public class Client { public static void main(String[] args) { Random random = new Random(); ArrayList<IWomen> arrayList = new ArrayList<IWomen>(); for (int i = 0; i < 5; i++) { arrayList.add(new Women(random.nextInt(4), "我要去逛街")); } // 定义三个请求对象 Father father = new Father(); Husband husband = new Husband(); Son son = new Son(); father.setNextHandler(husband); husband.setNextHandler(son); for (IWomen women : arrayList) { father.HandleMessage(women); } } }
运行结果:
-------母亲向儿子请示------- 母亲的请求是: 我要去逛街 儿子的答复是: 同意 -------妻子向丈夫请示------- 妻子的请求是: 我要去逛街 丈夫的答复是: 同意 -------母亲向儿子请示------- 母亲的请求是: 我要去逛街 儿子的答复是: 同意 -------没有地方请示了,按不同意处理------- -------妻子向丈夫请示------- 妻子的请求是: 我要去逛街 丈夫的答复是: 同意
在抽象类 Handler 中,我们设置了级别 level
的参数用来标示子类的等级;定义了 nextHandler
来制定当前节点的下一个处理节点。这样,每个子类在生成实例对象的时候,通过指定下一个节点,就可以生成责任链了。 责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果。其优点就是将请求和处理分开来了。请求者不需要知道谁将处理这个请求,处理者也不要知道谁发起了这个请求。两者解耦,提高了系统的灵活性。