Chain of responsibility-责任链模式
2018-06-08 本文已影响9人
oneWeekOneTopic
解决问题
它主要解决的问题是“递归、循环”问题或者大量的if-else 问题。通过定义不通的receiver,并在运行时决定receiver的执行顺序。它带来的一个好处是:receiver逻辑耦合(可以分不同的场景划分receiver逻辑), 代码结构清晰。
应用场景
信息或者请求 需要经过大量的if-else处理(转换成由多个receiver中的其中一个进行处理);
信息或请求 需要进行流水线处理(即需要经过层层加工)
原理图(UML)
imageHandler:持有nextHander对象,以便交下一个链条;并持有一个handle方法来处理请求
Receiver:实现Handler接口,并实现具体的处理逻辑
Sender:生成具有一定处理顺序的链条,并启动链条的头部来处理请求。
示例
这里我们举一个场景:去饭店吃饭,首先我们要向点餐员点菜、然后点餐员将菜名报给厨师、厨师做完菜之后将菜端到我们面前。
public abstract class Handler {
protected Handler nextHandler;
public abstract void handle();
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
}
public class OrderTaker extends Handler {
@Override
public void handle() {
System.out.println("请客人点餐");
System.out.println("客人点餐完成");
if (this.nextHandler != null) {
nextHandler.handle();
} else {
System.out.println("厨师下班了。。。");
}
}
}
public class Cooker extends Handler {
@Override
public void handle() {
System.out.println("为客人做菜");
System.out.println("做菜完成");
if (this.nextHandler != null) {
nextHandler.handle();
} else {
System.out.println("该招送餐员了。。。。");
}
}
}
public class Deliver extends Handler {
@Override
public void handle() {
System.out.println("将菜送到客人面前");
}
}
public class Manager {
public static void main(String[] args) {
// 组织结构
OrderTaker orderTaker = new OrderTaker();
Cooker cooker = new Cooker();
Deliver deliver = new Deliver();
orderTaker.setNextHandler(cooker);
cooker.setNextHandler(deliver);
// 来一个客人
orderTaker.handle();
}
}
下面的这种形式是一个变种,但其在各种基本组件中应用则更为广泛
spring -filter/interceptor都是采用的该模式,下面贴一部分OkHtpp中的对请求的处理源码。该示例参考:https://blog.csdn.net/yxhuang2008/article/details/72566928
public interface Interceptor {
Response intercept(Chain chain) throws IOException;
interface Chain{
Request request();
Response proceed(Request request) throws IOException;
}
}
public class BridgeInterceptor implements Interceptor{
@Override
public Response intercept(Chain chain) throws IOException {
Request userRequest = chain.request();
Response networkResponse = chain.proceed(userRequest);
System.out.println("BridgeInterceptor intercept");
return networkResponse;
}
}
public class CacheInterceptor implements Interceptor{
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
System.out.println("CacheInterceptor intercept");
return response;
}
}
public class ConnectInterceptor implements Interceptor{
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = new Response();
System.out.println("ConnectInterceptor intercept");
return response;
}
}
public class RealInterceptorChain implements Interceptor.Chain{
private final List<Interceptor> interceptors;
private final int index;
private final Request request;
private int calls;
public RealInterceptorChain(List<Interceptor> interceptors, int index, Request request) {
this.interceptors = interceptors;
this.index = index;
this.request = request;
}
@Override
public Request request() {
return request;
}
@Override
public Response proceed(Request request) throws IOException {
if (index >= interceptors.size()) {
throw new AssertionError();
}
calls++;
// Call the next interceptor in the chain.
RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
Interceptor interceptor = interceptors.get(index);
Response response = interceptor.intercept(next);
// Confirm that the next interceptor made its required call to chain.proceed().
if (index + 1 < interceptors.size() && next.calls != 1) {
throw new IllegalStateException("network interceptor " + interceptor
+ " must call proceed() exactly once");
}
// Confirm that the intercepted response isn't null.
if (response == null) {
throw new NullPointerException("interceptor " + interceptor + " returned null");
}
return response;
}
}
public class TempClient {
public static void main(String[] args) throws IOException {
List<Interceptor> interceptors = new ArrayList<Interceptor>();
interceptors.add(new BridgeInterceptor());
interceptors.add(new CacheInterceptor());
interceptors.add(new ConnectInterceptor());
Request request = new Request();
Interceptor.Chain chain = new RealInterceptorChain(interceptors, 0, request);
chain.proceed(request);
/**
* 执行结果, 倒序
* ConnectInterceptor intercept
* CacheInterceptor intercept
* BridgeInterceptor intercept
*/
}
}