引子
今天来看看什么是责任链模式。责任链,从字面意思可以看出,不同的责任连起来,成为一条责任链,针对不同的情况,在这条链上寻找对应的处理办法。
官方定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
责任链模式的重点是在“链”上,由一条链去处理相似的请求,在链中决定谁来处理这个请求,并返回相应的结果。
以下是通用类图:
在生活场景中,银行会针对存入不同的货币做出不同的处理,以下我们就用这个例子来说明责任链的使用方式。
抽象处理者
public abstract class BankHandler {
//不同的货币
public final static int RMB_LEVEL_REQUEST = 1;
public final static int USD_LEVEL_REQUEST = 2;
public final static int EUR_LEVEL_REQUEST = 3;
public final static int JPY_LEVEL_REQUEST = 4;
//能处理的级别
private int level = 0;
//责任传递,下一个责任处理是谁
private BankHandler nextHandler;
public BankHandler(int level) {
this.level = level;
}
//某一种货币(人民币、美元、欧元、日元)要求存入银行,要处理这个请求
public final void HandleMessage(IMoney money) {
if (money.getType() == this.level) {
this.response(money);
} else {
if (this.nextHandler != null) {
this.nextHandler.HandleMessage(money);
} else {
System.out.println("*******************************");
System.out.println("---处理不了的货币,按不处理对待!---");
System.out.println("*******************************");
}
}
}
//如果处理不了这个,告知下一个处理人
public void setNext(BankHandler handler) {
this.nextHandler = handler;
}
//有请求当然要回应
protected abstract void response(IMoney money);
}
具体处理者
public class RMB extends BankHandler {
public RMB() {
super(BankHandler.RMB_LEVEL_REQUEST);
}
@Override
protected void response(IMoney money) {
System.out.println("---我存RMB,帮我存入人民币账户---");
System.out.println(money.getRequest());
System.out.println("RMB处理完成,账户余额:¥66666");
}
}
public class USD extends BankHandler {
public USD() {
super(BankHandler.USD_LEVEL_REQUEST);
}
@Override
protected void response(IMoney money) {
System.out.println("---我存USD,帮我存入美元账户---");
System.out.println(money.getRequest());
System.out.println("USD处理完成,账户余额 :$88888");
}
}
public class EUR extends BankHandler {
public EUR() {
super(BankHandler.EUR_LEVEL_REQUEST);
}
@Override
protected void response(IMoney money) {
System.out.println("---我存EUR,帮我存入欧元账户---");
System.out.println(money.getRequest());
System.out.println("EUR处理完成,账户余额: €77777");
}
}
public class JPY extends BankHandler {
public JPY() {
super(BankHandler.JPY_LEVEL_REQUEST);
}
@Override
protected void response(IMoney money) {
System.out.println("---我存JPY,帮我存入日元账户---");
System.out.println(money.getRequest());
System.out.println("JPY处理完成,账户余额:円55555");
}
}
货币类
public class Money implements IMoney{
/*
通过一个int类型参数来描述货币的类型
1:人民币
2:美元
3:欧元
4:日元
*/
private int type = 0;
//货币的处理请求
private String request = "";
//构造函数传递过来请求
public Money(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;
break;
case 4:
this.request = "日元请求是:" + request;
}
}
//获得货币的类型
public int getType() {
return type;
}
//获得货币的处理请求
public String getRequest() {
return request;
}
}
货币接口
public interface IMoney {
//获得货币类型
int getType();
//获得货币处理请求
String getRequest();
}
测试类
public class Client {
public static void main(String[] args) {
//随机生成几种货币类型
Random random = new Random();
ArrayList<IMoney> arrayList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
arrayList.add(new Money(random.nextInt(5), "我想存钱"));
}
//定义四个请示对象
BankHandler rmb = new RMB();
BankHandler usd = new USD();
BankHandler eur = new EUR();
BankHandler jpy = new JPY();
//设置处理顺序
rmb.setNext(usd);
usd.setNext(eur);
eur.setNext(jpy);
for (IMoney m : arrayList) {
rmb.HandleMessage(m);
}
}
}
测试结果
责任链的优点
责任链模式非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性。
责任链的缺点
- 性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候。
- 调试不方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试逻辑更复杂。