当前位置 博文首页 > 韩超的博客 (hanchao5272):设计模式-责任链模式-以多轮面试为例
超级链接: Java常用设计模式的实例学习系列-绪论
参考:《HeadFirst设计模式》
责任链(Chain of Responsibility)模式是一种行为型
模式。
责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
本文以多轮面试
为场景来学习责任链模式
:
超级面试类:SuperInterview“
/**
* <p>超级面试类</P>
*
* @author hanchao
*/
@Slf4j
public class SuperInterview {
/**
* 针对普通求职者的面试过程
*/
public static String customInterview(String name) {
//笔试
log.info("[{}]开始参加笔试", name);
log.info("此轮笔试共计10道选择题,5到机试题,共计100分,答题时间60分钟。");
Integer score = RandomUtils.nextInt(40, 100);
if (score >= 60) {
log.info("[{}]笔试得分为{},通过了笔试。", name, score);
} else {
log.info("[{}]笔试得分为{},未通过了笔试。", name, score);
return "面试结果:未通过笔试";
}
log.info("[{}]进入下一轮面试。", name);
log.info("--------------------------------");
//技术面试
log.info("[{}]开始参加技术面试", name);
log.info("技术面试官先问了一些基础知识");
Boolean pass = RandomUtils.nextBoolean();
if (pass) {
log.info("[{}]基础知识回答得很完美,继续技术面试。", name);
} else {
log.info("[{}]基础知识掌握的很差,未通过了笔试。", name);
return "面试结果:未通过技术面试";
}
log.info("技术面试官又问了一些高级知识");
pass = RandomUtils.nextBoolean();
if (pass) {
log.info("[{}]高级知识回答得马马虎虎,继续技术面试。", name);
} else {
log.info("[{}]高级知识简直是不懂装通,未通过了笔试。", name);
return "面试结果:未通过技术面试";
}
log.info("[{}]进入下一轮面试。", name);
log.info("--------------------------------");
//HR面试
log.info("[{}]开始参加HR笔试", name);
log.info("HR先聊了聊公司的背景、现状、前景...");
log.info("[{}]反映很满意。");
log.info("HR开始谈工资。");
Integer percent = RandomUtils.nextInt(0, 50);
if (percent <= 25) {
log.info("[{}]期望工资涨幅为{}%,在HR承受范围内,通过了面试。", name, percent);
} else {
log.info("[{}]期望工资涨幅为{}%,超出HR承受范围内,未通过了面试。", name, percent);
return "面试结果:未通过HR面试";
}
log.info("[{}]进入下一轮面试。", name);
log.info("--------------------------------");
log.info("[{}]通过了所有面试,恭喜你!", name);
return "通过了所有面试,恭喜你!";
}
/**
* 针对高级求职者的面试过程
*/
public static String advancedInterview(String name) {
//技术面试
log.info("[{}]开始参加技术面试", name);
log.info("技术面试官先问了一些基础知识");
Boolean pass = RandomUtils.nextBoolean();
if (pass) {
log.info("[{}]基础知识回答得很完美,继续技术面试。", name);
} else {
log.info("[{}]基础知识掌握的很差,未通过了笔试。", name);
return "面试结果:未通过技术面试";
}
log.info("技术面试官又问了一些高级知识");
pass = RandomUtils.nextBoolean();
if (pass) {
log.info("[{}]高级知识回答得马马虎虎,继续技术面试。", name);
} else {
log.info("[{}]高级知识简直是不懂装通,未通过了笔试。", name);
return "面试结果:未通过技术面试";
}
log.info("[{}]进入下一轮面试。", name);
log.info("--------------------------------");
//HR面试
log.info("[{}]开始参加HR笔试", name);
log.info("HR先聊了聊公司的背景、现状、前景...");
log.info("[{}]反映很满意。");
log.info("HR开始谈工资。");
Integer percent = RandomUtils.nextInt(0, 50);
if (percent <= 25) {
log.info("[{}]期望工资涨幅为{}%,在HR承受范围内,通过了面试。", name, percent);
} else {
log.info("[{}]期望工资涨幅为{}%,超出HR承受范围内,未通过了面试。", name, percent);
return "面试结果:未通过HR面试";
}
log.info("[{}]进入下一轮面试。", name);
log.info("--------------------------------");
log.info("[{}]通过了所有面试,恭喜你!", name);
return "通过了所有面试,恭喜你!";
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
SuperInterview.customInterview("求职者" + i);
System.out.println();
}
}
}
缺点:
扩展性差
:如果增减面试环节,则必然会修改SuperInterview
,违背设计原则对修改关闭,对扩展放开
。复用性低
:如果针对不同的人群实施不同的面试安排,则需要写两个SuperInterview
,很多代码重复,代码复用低。灵活性差
:HR请假了,所以HR面试环节取消一段时间,这时需要注释掉所有HR面试代码;再HR请假结束之后,需要恢复所有HR面试代码。灵活性很差。首先,无论是笔试、技术面试还是HR面试,都是一轮面试,所以,抽象出面试抽象类:Interview
/**
* <p>一轮面试</P>
*
* @author hanchao
*/
@AllArgsConstructor
public abstract class AbstractInterview {
/**
* 下一轮面试
*/
@Getter
private AbstractInterview interview;
/**
* 面试
*/
public abstract String interview(String name);
}
然后,既然这个模式称之为责任链,什么是链?
可以拿链表进行理解,一轮面试相当于链表的一个节点。
那么,链表节点的结构时怎样的呢,大体如下:
public class Node {
/**
* 数据
*/
private String data;
/**
* 下一个节点
*/
private Node next;//指向下一个节点
//...
}
很容易想到,责任链模式的每个节点也是这种结构:包含下一个节点的引用。
根据上述分析,编写以下代码。
责任节点:笔试:ExamInterview
/**
* <p>笔试</P>
*
* @author hanchao
*/
@Slf4j
public class ExamInterview extends AbstractInterview {
public ExamInterview(AbstractInterview interview) {
super(interview);
}
/**
* 面试
*/
@Override
public String interview(String name) {
//笔试
log.info("[{}]开始参加笔试", name);
log.info("此轮笔试共计10道选择题,5到机试题,共计100分,答题时间60分钟。");
Integer score = RandomUtils.nextInt(40, 100);
if (score >= 60) {
log.info("[{}]笔试得分为{},通过了笔试。", name, score);
} else {
log.info