// 构造函数传递过来请求
public Women(int _type, String _request) {
this.type = _type;
this.request = _request;
}
// 获得自己的状况
public int getType() {
return this.type;
}
// 获得妇女的请求
public String getRequest() {
return this.request;
}
}
- IHandler(有处理权的人员接口):
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(“丈夫的答复是:同意”);
}
}
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 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 {
// 暂时什么也不做
}
}
}
}
首先是通过随机方法产生了5个古代妇女的对象,然后看她们是如何就看戏这件事去请示的,运行结果如下:
OK,业务已经实现了,但是明显这个业务实现是存在问题的。
● 职责界定不清晰
对女儿提出的请示,应该在父亲类中做出决定,父亲有责任、有义务处理女儿的请示, 因此Father类应该是知道女儿的请求自己处理,而不是在Client类中进行组装出来,也就是说原本应该是父亲这个类做的事情抛给了其他类进行处理。
● 代码臃肿
我们在Client类中写了if…else的判断条件,而且能随着能处理该类型的请示人员越多,if…else的判断就越多。
● 耦合过重
这是什么意思呢,我们要根据Women的type来决定使用IHandler的那个实现类来处理请 求。有一个问题是:如果IHandler的实现类继续扩展怎么办?如果修改Client类,那就违背了开闭原则。
● 异常情况欠考虑
妻子只能向丈夫请示吗?如果妻子(比如一个现代女性穿越到古代了,不懂什么“三从四德”)向自己的父亲请示了,父亲应该做何处理?我们的程序上可没有体现出来,逻辑失败了!
针对上面的问题,这时候就该考虑引入责任链模式了。
可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就 作出回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求,类似于如图16-3所示的顺序处理图:
图16-3:女性请示的顺序处理图
父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回应;要么把请求转发到后序环节。
根据责任链模式,修改后的类图如下:
图16-4:使用责任链模式后的女子“三从”类图
实现如下:
- 改造后的Handler类:
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);
}
在这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出 反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾, 则直接做不同意处理。基本方法response需要各个实现类实现,每个实现类只要实现两个职 责:一是定义自己能够处理的等级级别;二是对请求做出回应。
三个实现类如下:三个实现类分别处理不同等级的请求
- 父亲类:
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”);
}
}
- 儿子类:
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”);
}
}
-
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;
}
}
// 获得自己的状况
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 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);
}
}
}
在Client中设置请求的传递顺序,先向父亲请示,不是父亲应该解决的问题,则由父亲 传递到丈夫类解决,若不是丈夫类解决的问题则传递到儿子类解决,最终的结果必然有一个 返回,其运行结果如下所示:
业务调用类Client不用再去做判断到底是需要谁去处理,而且Handler抽象类的子类可以继续增加下去,只需要扩展传递链而已,调用类可以不用了解变化过程,甚至是谁在处理这个请求都不用知道。
==========================================================================
-
责任链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会 被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构, 由客户端负责链的创建,降低了系统的耦合度。
-
请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的 引用,可简化对象的相互连接。
-
在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动 态的增加或修改来增加或改变处理一个请求的职责。
-
在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新 建链即可,从这一点来看是符合“开闭原则”的。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。
为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的
并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)
66个Java面试知识点
架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)
算法刷题(PDF)
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。
为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的
并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)
[外链图片转存中…(img-yLxcC4K9-1712513472188)]
66个Java面试知识点
架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)
[外链图片转存中…(img-jSX65xMV-1712513472189)]
算法刷题(PDF)
[外链图片转存中…(img-AjoBW8gm-1712513472189)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!