職責鏈是一種行爲設計模式,容許你將請求沿着處理者鏈進行發送。收到請求後,每一個處理者都可對請求進行處理,或將其傳遞給鏈上的下個處理者。 java
在這種模式中,一般每一個接收者都包含對另外一個接收者的引用。若是一個對象不能處理該請求,那麼它會把相同的請求傳給下一個接收者,依此類推,直到有對象處理它爲止(也可能沒有),如此使得每一個接收者都有機會接收和處理請求。設計模式
對於調用者來講,調用者只須要將請求發送到職責鏈上便可,無須關心請求的處理細節和請求的傳遞,因此責任鏈也將請求的發送者和處理者進行了解耦。緩存
一個事件須要通過多個對象處理是一個挺常見的場景,譬如客服諮詢流程,採購審批流程,請假流程,軟件開發中的異常處理流程,過濾系統等各類各樣的流程,能夠考慮使用責任鏈模式來實現。 cookie
如圖,假如你剛購置了一個新的硬件設備,可是鏈接上電腦並不能正確執行,因而你決定撥打技術支持電話。網絡
首先你會聽到自動回覆器的機器合成語音,它提供了針對各類問題的九個經常使用解決方案,你按照提示操做,機器人將你轉接到一位人工客服人員。dom
客服發現問題的技術性比較強,沒法提供任何具體的解決方案。因而他將你轉接到一位技術工程師。ide
最後,工程師告訴了你新硬件設備驅動程序的下載網址,以及操做步驟,你按照說明解決了問題,幾經周折,終於大功告成。 函數
以請假流程爲例,通常公司普通員工的請假流程簡化以下 ui
普通員工發起一個請假申請,當請假天數小於3天時主管便可審批;當請假天數大於3天時,須要提交給項目經理審批,但若請假天數大於7天,就要提交給總經理審批。public interface Handler {
/** * 處理請假 * * @param days 請假天數 * @return 是否批准 */
boolean handleHoliday(int days);
/** * 設置責任鏈的下一個處理者 * * @param h 下一個處理者 */
void setNext(Handler h);
}
public class BaseHandler implements Handler {
private Handler next;
@Override
public boolean handleHoliday(int days) {
if (next != null) {
return next.handleHoliday(days);
} else {
System.out.println("未批准");
return false;
}
}
@Override
public void setNext(Handler h) {
next = h;
}
}
public class LeaderManager extends BaseHandler {
@Override
public boolean handleHoliday(int days) {
if (days <= 3) {
System.out.println("LeaderManager 批准");
return true;
} else {
return super.handleHoliday(days);
}
}
}
public class ProjectManager extends BaseHandler {
@Override
public boolean handleHoliday(int days) {
if (days <= 7) {
System.out.println("ProjectManager 批准");
return true;
} else {
return super.handleHoliday(days);
}
}
}
public class DeptManager extends BaseHandler {
@Override
public boolean handleHoliday(int days) {
System.out.println("DeptManager 批准");
return true;
}
}
public class Client {
public static void main(String[] args) {
Handler leaderManager = new LeaderManager();
Handler projectManager = new ProjectManager();
Handler deptManager = new DeptManager();
leaderManager.setNext(projectManager);
projectManager.setNext(deptManager);
leaderManager.handleHoliday(5);
}
}
// Logcat:
// ProjectManager 批准
複製代碼
Android 事件傳遞機制this
public boolean dispatchTouchEvent(MotionEvent event){
boolean consume = false;
if (onInterceptTouchEvent(event)) {
consume = onTouchEvent(event);
} else {
consume = child.dispatchTouchEvent(event);
}
return consume;
}
複製代碼
「一個純的責任鏈模式要求一個具體的處理者對象只能在兩個行爲中選擇一個:一是承擔責任,而是把責任推給下家。不容許出現某一個具體處理者對象在承擔了一部分責任後又把責任向下傳的狀況。
在一個純的責任鏈模式裏面,一個請求必須被某一個處理者對象所接收;在一個不純的責任鏈模式裏面,一個請求能夠最終不被任何接收端對象所接收。
純的責任鏈模式的實際例子很難找到,通常看到的例子均是不純的責任鏈模式的實現。有些人認爲不純的責任鏈根本不是責任鏈模式,這也許是有道理的。可是在實際的系統裏,純的責任鏈很難找到。若是堅持責任鏈不純便不是責任鏈模式,那麼責任鏈模式便不會有太大意義了。 」
Router?
OkHttp Interceptor
/** * 項目中自定義的 Interceptor */
object DomainSwitchInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val requestDomain = request.url().host()
val domainManager = DomainManagerFactory.getInstance().getDomainManagerByDomain(requestDomain)
val currentDomain = domainManager?.pickHostWithoutSchema()
if (currentDomain != null && requestDomain != currentDomain) {
request = request.newBuilder()
.url(request.url().newBuilder().host(currentDomain).build())
.build()
}
return chain.proceed(request)
}
}
/** * 將自定義 Interceptor 添加到 OkHttp * 最終添加到 OkHttpClient 靜態內部類 Builder 的 final List<Interceptor> interceptors 中 */
object RetrofitRestClient {
val defaultOkHttpClient: OkHttpClient by lazy {
VolleyManager.getOkHttpClient()
.newBuilder()
.addInterceptor(RequestCommonParamsInterceptor)
.addInterceptor(DomainSwitchInterceptor)
.addInterceptor(RequestMonitorInterceptor)
.dns(HttpDns)
.build()
}
}
/** * 全部請求都是從 OkHttp 的 RealCall 的 getResponseWithInterceptorChain() 方法開始 */
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors()); // 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 放入 RealInterceptorChain 構造責任鏈
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
/** * OkHttp Interceptor */
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
/** * 構建責任鏈的接口 */
interface Chain {
Request request();
Response proceed(Request request) throws IOException;
@Nullable Connection connection();
Call call();
int connectTimeoutMillis();
Chain withConnectTimeout(int timeout, TimeUnit unit);
int readTimeoutMillis();
Chain withReadTimeout(int timeout, TimeUnit unit);
int writeTimeoutMillis();
Chain withWriteTimeout(int timeout, TimeUnit unit);
}
}
/** * Chain 的實現類 RealInterceptorChain 的 proceed 方法 */
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
if (index >= interceptors.size()) throw new AssertionError();
calls++;
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
return response;
}
複製代碼
Article by Panxc