前言
最近查看OkHttp 請(qǐng)求框架膝晾,發(fā)現(xiàn)里面過濾器用的非常靈活币喧,而其整個(gè)設(shè)計(jì)模式就是采用責(zé)任鏈模式來(lái)設(shè)計(jì)的,這篇博客主要用來(lái)討論一下責(zé)任鏈相關(guān)設(shè)計(jì)與使用。
責(zé)任鏈模式
一個(gè)事件需要經(jīng)過多個(gè)對(duì)象處理是一個(gè)挺常見的場(chǎng)景蜓萄,譬如采購(gòu)審批流程,請(qǐng)假流程澄峰。同樣網(wǎng)絡(luò)請(qǐng)求中也存在一些列的流程嫉沽,這也是OkHttp采用該模式的主要原因。下面以一個(gè)采購(gòu)場(chǎng)景來(lái)作說(shuō)明:
代碼實(shí)現(xiàn):
Employee
public class Employee {
private String name;
private String msg;
private int price;
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
ApplyFilter
public interface ApplyFilter {
boolean doFilter(Employee employee,ApplyFilterChain chain);
}
ApplyFilterChain
public class ApplyFilterChain implements ApplyFilter {
List<ApplyFilter> filters = new ArrayList<>();
int index = 0;
public ApplyFilterChain add(ApplyFilter applyFilter){
filters.add(applyFilter);
return this;
}
@Override
public boolean doFilter(Employee employee,ApplyFilterChain chain) {
if (index>=filters.size()) return false;
ApplyFilter filter = filters.get(index);
index ++;
filter.doFilter(employee,chain);
return true;
}
}
SupervisorApplyFilter
/**
* 主管審批
*/
public class SupervisorApplyFilter implements ApplyFilter{
@Override
public boolean doFilter(Employee employee,ApplyFilterChain chain) {
if (employee.getPrice()<=100){
System.out.println("資金小于100主管審批通過,流程結(jié)束");
employee.setMsg(employee.getMsg()+"資金小于100主管審批通過魂毁,流程結(jié)束");
return false;
}else {
System.out.println("資金大于100主管請(qǐng)經(jīng)理審批");
employee.setMsg(employee.getMsg()+"資金大于100主管請(qǐng)經(jīng)理審批->");
chain.doFilter(employee,chain);
return true;
}
}
}
ManagerApplyFilter
/**
* 經(jīng)理審批
*/
public class ManagerApplyFilter implements ApplyFilter{
@Override
public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
if (employee.getPrice()<=500){
System.out.println("資金小于500經(jīng)理審批通過玻佩,流程結(jié)束");
employee.setMsg(employee.getMsg()+"資金小于500經(jīng)理審批通過,流程結(jié)束");
return false;
}else {
System.out.println("資金大于500經(jīng)理請(qǐng)總經(jīng)理審批");
employee.setMsg(employee.getMsg()+"資金大于500經(jīng)理請(qǐng)總經(jīng)理審批->");
chain.doFilter(employee,chain);
return true;
}
}
}
GeneralManagerApplyFilter
/**
* 總經(jīng)理審批
*/
public class GeneralManagerApplyFilter implements ApplyFilter{
@Override
public boolean doFilter(Employee employee ,ApplyFilterChain chain) {
if (employee.getPrice()<=5000){
System.out.println("資金小于5000總經(jīng)理審批通過席楚,流程結(jié)束");
employee.setMsg(employee.getMsg()+"資金小于5000總經(jīng)理審批通過夺蛇,流程結(jié)束");
return false;
}else {
System.out.println("資金大于5000, 總經(jīng)理需要開會(huì)討論,流程結(jié)束");
employee.setMsg(employee.getMsg()+"資金大于5000, 總經(jīng)理需要開會(huì)討論酣胀,流程結(jié)束");
return true;
}
}
}
以上為一個(gè)完整的chain
如果中間某個(gè)環(huán)節(jié)可以結(jié)束該流程,則后續(xù)的流程不用處理娶聘,這也是通過doFilter
的返回值來(lái)確定下一個(gè)流程是否繼續(xù)闻镶,這個(gè)是一個(gè)遞歸的思想,也是比較難以理解的地方丸升。
Main
public class Main {
public static void main(String[] args) {
Employee employee = new Employee();
employee.setMsg("物料采購(gòu)申請(qǐng)->");
employee.setPrice(10);
ApplyFilterChain applyFilterChain = new ApplyFilterChain();
applyFilterChain.add(new SupervisorApplyFilter()).add(new ManagerApplyFilter()).add(new GeneralManagerApplyFilter());
applyFilterChain.doFilter(employee,applyFilterChain);
System.out.println(employee.getMsg());
}
}
得出的結(jié)果如下:
資金小于100主管審批通過铆农,流程結(jié)束
物料采購(gòu)申請(qǐng)->資金小于100主管審批通過,流程結(jié)束
以上是關(guān)于責(zé)任鏈模式的使用狡耻。
3 OkHttp
關(guān)于OkHttp 中過濾器的問題可以查看到RealCall類中:
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
其不斷添加過濾器墩剖,但最后的過濾器為CallServerInterceptor
由此可以得出結(jié)論,最終請(qǐng)求網(wǎng)絡(luò)等想過操作夷狰,就是在該類中進(jìn)行岭皂,查看代碼果真如此。
以上是關(guān)于在OkHttp中發(fā)現(xiàn)的責(zé)任鏈模式的使用沼头,其詳細(xì)介紹可以參考設(shè)計(jì)模式 | 責(zé)任鏈模式及典型應(yīng)用這篇文章寫得比較清楚爷绘。