前言
-
- 责任链模式是行为型模式之一,由于其构成要素简单清晰,理解起来较为简单。
- 因此本篇博客我举一个极其简单的例子来说明一下它的基本构成,然后梳理一下它的一些特点
- 文章最后我将结合简单工厂把程序稍微改进一下
理解
-
- 责任链模式中里面的每个对象都持有对下一个对象的引用,因此连成一条链,所以是责任链,责任说的就是要做的事,请求会在链端开始传递,直到有一个合适的对象处理这个请求,否则就一直传递到链尾。
我们先看一个例子就知道责任链是干啥的了
情景引入
小明是个大学学生,在校不喜欢上课课,但是他痴迷编程,他在学设计模式的时候被里面的责任链模式深深吸引,于是打算请假专心学习。已知学校里请假班长可以批短期假,老师可以批长期假,辅导员可以批超长期假,根据以上内容改成责任链例子。
首先明确责任链的两个角色
抽象处理者 | 定义一个处理请求的接口 |
具体处理者 | 保留一个引用(后面被指定为下家的引用),处理请求或者传递给下家 |
我程序的类图
java源程序
抽象处理类
首先要注意到抽象类内部保存的引用是它自身的,但是由于有多个子类,所以可以指定是哪个具体子类的。而子类也都继承了set方法因此是可以指定的。
package responsibility;
public abstract class Handler {
Handler handler;//注意这是自身的实例
public void setHander(Handler handler) {
this.handler = handler;
}
public abstract void handleRequest(String a, int b);//处理请求
}
班长
例如班长类里的handler是从父类继承的,但是客户端在实例化后的时候调用了set方法,因此里面的handler传入的其实是老师的对象,因此一旦调用请求就由老师去处理啦,后面也是这个道理,因此才把对象串成链。
package responsibility;
public class MonitorHandler extends Handler{
public void handleRequest(String a, int b) {
if(b<=2){
System.out.println("班长同意"+a+"请假"+b+"天");
}else{
System.out.println("班长说:请假时间太长,我去问问老师");
handler.handleRequest(a, b);//此时的handler是老师的对象
}
}
}
老师
package responsibility;
public class TeacherHandler extends Handler{
public void handleRequest(String a, int b) {
if(b<=7){
System.out.println("老师同意"+a+"请假"+b+"天");
}else{
System.out.println("老师说:请假时间太长,我去问问你们辅导员");
handler.handleRequest(a, b);
}
}
}
导员
package responsibility;
public class DirectorHandler extends Handler{
public void handleRequest(String a, int b) {
if(b<=15){
System.out.println("辅导员同意"+a+"请假"+b+"天");
}else{
System.out.println("请这么多天,你是想挂科了吧,不同意");
}
}
}
客户端
package responsibility;
public class Client {
public static void main(String[] args) {
Handler dh=new DirectorHandler();
Handler th=new TeacherHandler();
Handler mh=new MonitorHandler();
mh.setHander(th);//让班长持有老师的引用
th.setHander(dh);//老师持有导员的引用
mh.handleRequest("小明", 15);
}
}
运行结果
程序分析
程序比较简单,调用过程我在例子中也说明了。现在我们的程序很明显,请假根据请假时间是逐层上报的,直到有一个上级批准它或者最后不同意,这也是责任链的工作方式,请求会从链前端传入,直到有一个类符合处理条件就处理掉它。
责任链模式的应用场景
- 责任链的这种工作方式其实最容易让人想到的就是Filter了,过滤器会拦截请求,但是责任链又有区别,因此责任链拦截处理就结束了,过滤器的操作就不一定。
- 经常被使用在窗口系统中,处理鼠标键盘事件。
- 当然只要有多个对象可以处理同一个请求,而具体处理只能运行时确定这种情况都可以考虑使用该模式
责任链模式优点
- 请求的发送者与接收者实现了解耦
- 系统可以在不影响客户端的情况下动态的重新组织链和分配责任。
缺点
- 不能保证请求会被处理,请求可能走到链尾也得不到处理
- 会影响系统性能
引入简单工厂模式
由于客户端创建对象又设置依赖,看着太不美观啦,所以引入一个简单工厂把对象的创建都封装起来,这样就实现了客户端和对象创建的解耦
引入工厂类
package responsibility;
public class ApproveFactory {
//把对象的创建以及依赖关系封装进工厂
Handler dh=new DirectorHandler();
Handler th=new TeacherHandler();
Handler mh=new MonitorHandler();
public Handler getMonitor(){
mh.setHander(th);
th.setHander(dh);
return mh;//返回班长实例
}
}
客户端改为
package responsibility;
public class Client {
public static void main(String[] args) {
ApproveFactory af=new ApproveFactory();
Handler mh=af.getMonitor();//取得班长实例
mh.handleRequest("小明", 6);
}
}
运行结果为