责任链模式
一、特性与定义
1. 定义
对于一个请求,可能会有若干个对象会去处于它,但是并不一定每个对象都会处理它。这时候,我们为请求创建一个接收者对象的链,每个接收者都包含对另一个对象的引用,当某个接收者不能处理该请求时,会将该请求转给下一个接收者处理。
Spring和Tomcat中的过滤器使用的也是责任链模式。
2. 角色
1). 处理者(Handler): 处理者是一个接口,负责规定具体者处理用户请求的方法以及具体处理者设置后继对象的方法,如以下代码中的handleRequest()、setNextHandler()方法。
2). 具体处理者(ConcreteHandler): 具体处理者是实现处理者接口的类的实例。具体处理者通过调用处理者接口规定的方法处理用户的请求,即在接到用户的请求后,处理者将调用接口规定的方法,在执行该方法的过程中,如果发现能处理用户的请求,就处理有关的数据,否则就反馈无法处理的信息给用户,然后将用户的请求传递给自己的后继对象。
责任链模式图解3. 优点
1). 责任链中的对象只和自己的后继是弱耦合关系,和其它对象毫无关联,这使得编写处理对象以及创建责任链变得非常容易;
2). 当在处理者中分配职责时,责任链给应用程序更多的灵活性;
3). 应用程序可以动态地增加、删除处理者或重新指派处理者的职责;
4). 应用程序可以动态地改变处理者之间的先后顺序;
5). 使用责任链的用户不必知道处理者的信息,用户不必知道到底是哪个对象处理了它的请求。
4. 缺点
1). 不能保证请求一定被接收;
2). 系统性能将受到一定影响,调试时不方便,可能会造成循环调用。
二、代码实现
案例:判断一个车牌号码是否属于北京、上海或天津地区的车牌号码。
1. 处理者接口
public interface Handler {
public abstract void handlerRequester(String number);
public abstract void setNextHandler(Handler handler);
}
2. 北京类
public class BeiJing implements Handler{
//存放当前处理者后继的Handler接口变量
private Handler handler;
//存放号码(实际项目应该是数据库)
private ArrayList<String> numberList;
BeiJing() {
numberList = new ArrayList<String>();
//这里使用模拟号码
numberList.add("京AKS987");
numberList.add("京H67893");
numberList.add("京FM67A5");
numberList.add("京C56799");
}
@Override
public void handlerRequester(String number) {
if (numberList.contains(number)) {
System.out.println("车牌" + number + "属于北京地区");
} else {
System.out.println("车牌" + number + "不属于北京地区");
if (handler != null)
//将请求传递给下一个处理者
handler.handlerRequester(number);
}
}
@Override
public void setNextHandler(Handler handler) {
this.handler = handler;
}
}
3. 上海类
public class ShangHai implements Handler {
private Handler handler;
private ArrayList<String> numberList;
ShangHai() {
numberList = new ArrayList<String>();
//这里使用模拟号码
numberList.add("沪AKS987");
numberList.add("沪H67893");
numberList.add("沪FM67A5");
numberList.add("沪C56799");
}
@Override
public void handlerRequester(String number) {
if (numberList.contains(number)) {
System.out.println("车牌" + number + "属于上海地区");
} else {
System.out.println("车牌" + number + "不属于上海地区");
if (handler != null)
//将请求传递给下一个处理者
handler.handlerRequester(number);
}
}
@Override
public void setNextHandler(Handler handler) {
this.handler = handler;
}
}
4. 天津类
public class TianJin implements Handler {
private Handler handler;
private ArrayList<String> numberList;
TianJin() {
numberList = new ArrayList<String>();
//这里使用模拟号码
numberList.add("津AKS987");
numberList.add("津H67893");
numberList.add("津FM67A5");
numberList.add("津C56799");
}
@Override
public void handlerRequester(String number) {
if (numberList.contains(number)) {
System.out.println("车牌" + number + "属于天津地区");
} else {
System.out.println("车牌" + number + "不属于天津地区");
if (handler != null)
//将请求传递给下一个处理者
handler.handlerRequester(number);
}
}
@Override
public void setNextHandler(Handler handler) {
this.handler = handler;
}
}
5. 初始化并发起请求类
public class Application {
public static void main(String[] args) {
Handler beiJing, shangHai, tianJin;
beiJing = new BeiJing();
shangHai = new ShangHai();
tianJin = new TianJin();
beiJing.setNextHandler(shangHai);
shangHai.setNextHandler(tianJin);
beiJing.handlerRequester("京AKS987");
System.out.println();
beiJing.handlerRequester("沪H67893");
System.out.println();
beiJing.handlerRequester("津C56799");
System.out.println();
beiJing.handlerRequester("辽B88881");
}
}