生活场景:
1.销售员------销售经理-----部门经理----CEO 处理客户打折的折扣
2. 需求开发例子
假设现在有个需求来了,首先是实习生拿到这个需求。
如果实习生能够实现,直接实现。如果不行,他把这个需求交给初级工程师。
如果初级工程师能够实现,直接实现。如果不行,交给中级工程师。
如果中级工程师能够实现,直接实现。如果不行,交给高级工程师。
如果高级工程师能够实现,直接实现。如果不行,交给 CTO。
如果 CTO能够实现,直接实现。如果不行,直接跟产品说,需求不做。
3. 比如会员等级系统,会员等级之间构成一条链,用户发起一个请求,系统只要把请求分发到责任链模式的入口,直到传递到与用户会员匹配的等级,这样各个会员等级的业务逻辑就会变成很清晰。
定义
创建多个对象,使这些对象形成一条链,并沿着这条链传递请求,直到链上的某一个对象决定处理此请求。
我的介绍:顾名思义,责任链模式是一条链,链上有多个节点,每个节点都有各自的责任。当有输入时,第一个责任节点看自己能否处理该输入,如果可以就处理。如果不能就交由下一个责任节点处理。依次类推,直到最后一个责任节点。
特点
1)接收请求的对象连接成一条链,对象之间存在层级关系。
2)这些对象可处理请求,也可传递请求,直到有对象处理该请求。
责任链模式涉及到的角色
- 抽象处理者角色:定义了处理请求的接口或者抽象类,提供了处理请求的的方法和设置下一个处理者的方法。(2个方法)
- 具体处理者角色:实现或者继承抽象这角色,具体逻辑根据实际的架构来定,后面会提到
看下这个代码
String input = "1";
switch (input) {
case "1":
//TODO do something
break;
case "2":
//TODO do something
break;
case "3":
//TODO do something
break;
default:
//TODO do something
break;
}
实战
先来看抽象处理者角色代码:
public abstract class Handler {
private Handler nextHandler;
private int level;
public Handler(int level) {
this.level = level;
}
// 处理请求传递,注意final,子类不可重写
public final void handleMessage(Demand demand) {
if (level == demand.demandLevel()) {
this.report(demand);
} else {
if (this.nextHandler != null) {
System.out.println("事情太严重,需报告上一级");
this.nextHandler.handleMessage(demand);
} else {
System.out.println("我就是boss,没有上头");
}
}
}
public void setNextHandler(Handler handler) {
this.nextHandler = handler;
}
// 抽象方法,子类实现
public abstract void report(Demand demand);
}
两个角色都定义好了,来看客户端如何实现:
public class Client {
public static void main(String[] args) {
Demand demandA = new DemandA(); // 请求等级低
Demand demandB = new DemandB(); // 请求等级高
Boss boss = new Boss();
TechnicalManager technicalManager = new TechnicalManager();
technicalManager.setNextHandler(boss); // 设置下一级
technicalManager.handleMessage(demandA);
System.out.println("============================");
technicalManager.handleMessage(demandB);
}
}
两个角色都定义好了,来看客户端如何实现:
public class Client {
public static void main(String[] args) {
Demand demandA = new DemandA(); // 请求等级低
Demand demandB = new DemandB(); // 请求等级高
Boss boss = new Boss();
TechnicalManager technicalManager = new TechnicalManager();
technicalManager.setNextHandler(boss); // 设置下一级
technicalManager.handleMessage(demandA);
System.out.println("============================");
technicalManager.handleMessage(demandB);
}
}
结果可以看到,级别低的请求技术经理自己处理,级别高的传递给了下一级的Boss,这样就形成一条链,而这也是责任链的核心所在。
注意,在请求的传递过程中,请求是不会发生变化的
注意:中间插入角色,不需要改动什么代码,只需要再扩展。
比如开始的案例中:添加高级经理
四、责任链模式的优缺点
优点
1)降低耦合度:客户端不需要知道请求由哪个处理者处理,而处理者也不需要知道处理者之间的传递关系,由系统灵活的组织和分配。
2)良好的扩展性:增加处理者的实现很简单,只需重写处理请求业务逻辑的方法。
缺点
1)请求会从链头发出,直到有处理者响应,在责任链比较长的时候会影响系统性能。
2)请求递归,调试排错比较麻烦。
(不需要知道中间是谁处理的,只需要抛出一个请求,有人会处理)
其实责任链模式就是在某种场景下:有一个请求需要处理,但是最终处理者又不确定的时候采用的一种模式。 但是其处理者对于客户端是透明的,无需知道谁将处理这个请求,只需要抛出请求,拿到结果即可。
安卓中的应用
1.okhttp
2.责任链模式思想在Android源码中的体现莫过于:
触摸事件的处理和分发了。每当用户接触屏幕时,Android都会将其打包成一个MotionEvent对象从ViewTree自顶而下的分发处理。 代码过多
再举例:
举个例子,我们的图片需要设计三级缓存,那么它是怎么取缓存的呢?
AbsCacheManager bmpCache = new MemoryCache();
Bitmap bmp = bmpCache.getCache(cacheKey);
复制代码
先定义一个缓存抽象类
public abstract class AbsCacheManager {
protected AbsCacheManager mCache;
// 获取Bitmap
public abstract Bitmap getCache(String cacheKey);
public void setNextHandler(AbsCacheManager manager) {
mCache = manager;
}
public AbsCacheManager getNextHandler() {
return mCache;
}
}
复制代码
下面是具体实施者:内存缓存,磁盘缓存,网络获取
public class MemoryCache extends AbsCacheManager {
public Bitmap getCache(String cacheKey) {
Bitmap bmp = getCacheFromMemory(cacheKey);
// 如果内存缓存为空,则将请求传递给下一位:磁盘缓存来处理
if (bmp == null) {
setNextHandler(new DiskCache());
bmp = getNextHandler().getCache(cacheKey);
}
return bmp;
}
}
public class DiskCache extends AbsCacheManager {
public Bitmap getCache(String cacheKey) {
Bitmap bmp = getCacheFromDisk(cacheKey);
// 如果磁盘缓存为空,则将请求传递给下一位:网络图片下载来处理
if (bmp == null) {
setNextHandler(new NetworkFetchManager());
bmp = getNextHandler().getCache(cacheKey);
}
return bmp;
}
}
public class NetworkFetchManager extends AbsCacheManager {
public Bitmap getCache(String cacheKey) {
Bitmap bmp = getCacheFromNetWork(cacheKey);
return bmp;
}
}
一条责任链跃然纸上:内存—>磁盘->网络。
参考博客:
https://juejin.im/post/5a126b146fb9a0450c490201