首页 >> 大全

读书 | 设计模式之禅 - 责任链模式

2023-10-14 大全 29 作者:考证青年

文章目录

1. 实现古代妇女的“三从”制度

一位女性在结婚之前要听从于父亲,结婚之后要听从于丈夫,如果丈夫死了还要听从于儿子。作为父亲、丈夫或儿子,只有两种选择:要不承担起责任来,允许她或不允许她逛街;要不就让她请示下一个人,这是整个社会体系的约束。

下面来看如何通过程序来实现“三从”,需求很简单:通过程序描述一下古代妇女的“三从”制度。

对应的类图:是三个有决策权对象的接口,是女性的代码

① 接口

public interface IWomen {/*** 获得个人状况** @return 结婚了还是没结婚、丈夫是否在世*/int getType();/*** 获得个人请示* @return 你要干什么?出去逛街?约会?还是看电影?*/String getRequest();
}

② Women 实现类

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

③ 接口

public interface IHandler {/*** 一个女性(女儿、妻子或者母亲)要求逛街,你要处理这个请求*/public void HandleMessage(IWomen women);
}

④ 实现类

public class Father implements IHandler {/*** 未出嫁的女儿来请示父亲*/public void HandleMessage(IWomen women) {System.out.println("女儿的请示是:" + women.getRequest());System.out.println("父亲的答复是:同意");}
}

⑤ 实现类

public class Husband implements IHandler {/*** 妻子向丈夫请示*/public void HandleMessage(IWomen women) {System.out.println("妻子的请示是:" + women.getRequest());System.out.println("丈夫的答复是:同意");}
}

⑥ Son 实现类

public class Son implements IHandler {/*** 母亲向儿子请示*/public void HandleMessage(IWomen women) {System.out.println("母亲的请示是:" + women.getRequest());System.out.println("儿子的答复是:同意");}
}

⑦ 测试类

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);} 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 {//暂时什么也不做}}}
}

上述代码实现存在职责界定不清晰,代码臃肿,耦合过重,异常情况欠考虑等问题。

2. 实现古代妇女的“三从”制度-优化

女性提出一个请示,必然要获得一个答复,甭管是同意还是不同意,总之是要一个答复的,而且这个答复是唯一的,不能说是父亲作出一个决断,而丈夫也作出了一个决断,也即是请示传递出去,必然有一个唯一的处理人给出唯一的答复。

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

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

三个实现类、、Son只要实现构造函数和父类中的抽象方法就可以了,具体由谁处理女性提出的请求,都已经转移到了抽象类中。

① 抽象类

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("--------女儿向父亲请示-------");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("--------妻子向丈夫请示-------");System.out.println(women.getRequest());System.out.println("丈夫的答复是:同意\n");}
}

④ Son 子类

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

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

⑤ 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;default:}}//获得自己的状况public int getType() {return this.type;}//获得妇女的请求public String getRequest() {return this.request;}
}

⑥ 测试类

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

在中设置请求的传递顺序,先向父亲请示,不是父亲应该解决的问题,则由父亲传递到丈夫类解决,若不是丈夫类解决的问题则传递到儿子类解决,最终的结果必然有一个返回。

3. 责任链模式的定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果:

① 抽象类

public abstract class Handler {private Handler nextHandler;//每个处理者都必须对请求做出处理//被final修改的抽象方法不能被继承public final Response handleMessage(Request request) {Response response = null;//判断是否是自己的处理级别if (this.getHandlerLevel().equals(request.getRequestLevel())) {response = this.echo(request);} else { //不属于自己的处理级别//判断是否有下一个处理者if (this.nextHandler != null) {response = this.nextHandler.handleMessage(request);} else {//没有适当的处理者,业务自行处理}}return response;}//设置下一个处理者是谁public void setNext(Handler _handler) {this.nextHandler = _handler;}//每个处理者都有一个处理级别protected abstract Level getHandlerLevel();//每个处理者都必须实现处理任务protected abstract Response echo(Request request);
}

② 处理者子类

public class ConcreteHandler1 extends Handler {/*** 定义自己的处理逻辑*/protected Response echo(Request request) {//完成处理逻辑return null;}/*** 设置自己的处理级别*/protected Level getHandlerLevel() {//设置自己的处理级别return null;}
}

③ 处理者子类

public class ConcreteHandler2 extends Handler {/*** 定义自己的处理逻辑*/protected Response echo(Request request) {//完成处理逻辑return null;}/*** 定义自己的处理逻辑*/protected Level getHandlerLevel() {//设置自己的处理级别return null;}
}

④ 处理者子类

public class ConcreteHandler3 extends Handler {/*** 定义自己的处理逻辑*/protected Response echo(Request request) {//完成处理逻辑return null;}/*** 设置自己的处理级别*/protected Level getHandlerLevel() {//设置自己的处理级别return null;}
}

⑤ 测试类

public class Client {public static void main(String[] args) {//声明所有的处理节点Handler handler1 = new ConcreteHandler1();Handler handler2 = new ConcreteHandler2();Handler handler3 = new ConcreteHandler3();//设置链中的阶段顺序1-->2-->3handler1.setNext(handler2);handler2.setNext(handler3);//提交请求,返回结果Response response = handler1.handlerMessage(new Request());}
}

责任链在实际的项目中使用也是比较多的,我曾经做过这样一个项目,界面上有一个用户注册功能,注册用户分两种,一种是VIP用户,也就是在该单位办理过业务的,一种是普通用户,一个用户的注册要填写一堆信息,VIP用户只比普通用户多了一个输入项:VIP序列号。注册后还需要激活,VIP和普通用户的激活流程也是不同的,VIP是自动发送邮件到用户的邮箱中就算激活了,普通用户要发送短信才能激活,为什么呢?获得手机号码以后好发广告短信啊!项目组就采用了责任链模式,甭管从前台传递过来的是VIP用户信息还是普通用户信息,统一传递到一个处理入口,通过责任链来完成任务的处理。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了