1. Definition and usage scenario of responsibility chain pattern
Definition:
Responsibility chain model is one of the behavioral design models. It enables multiple objects to process requests, thus avoiding the coupling between the sender and the recipient of requests. Connect these objects into a chain and pass the request along that chain until an object handles it.
Use scenarios:
It enables multiple objects to process requests, thus avoiding the coupling between the sender and the receiver of requests. Connect these objects into a chain and pass the request along that chain until the object processes it.
2. Advantages and disadvantages of responsibility chain model
2.1 advantages
The obvious advantage of the responsibility chain model is that it separates requests from processing. The requester may not need to know who is handling the request, and the processor may not need to know the whole picture of the request. The decoupling of the two improves the flexibility of the system.
2.2 disadvantages
There are two obvious shortcomings in the chain of responsibility: one is the performance problem. Every request traverses from the chain head to the end, especially when the chain is long, the performance is a big problem.
Second, debugging is inconvenient, especially when the chain is long and there are many links. Because of the similar recursive way, the logic of debugging may be more complex.
3. Attention to Realization
The number of nodes in the chain needs to be controlled to avoid the occurrence of overlong chains. The general approach is handler.
Set a maximum number of nodes in the setNext method to determine whether it has exceeded its threshold, and if it has exceeded, it will not allow the chain to be established, so as to avoid unconscious damage to system performance.
4. Realization of Responsibility Chain Model
public abstract class AbstractRequest {
private Object obj;//Processing objects
public AbstractRequest(Object object) {
this.obj = object;
}
public Object getContent() {
return obj;
}
//Get the level of the request
public abstract int getRequestLevel();
}
public abstract class AbstractHandler {
protected AbstractHandler nexthandler;//Next node processes objects
public final void handleRequest(AbstractRequest request) {
if(getHandleLevel()==request.getRequestLevel()){
handle(request);
}else{
if(nexthandler!=null){
nexthandler.handleRequest(request);
}else{
System.out.println("All of handler can not handle the request");
}
}
}
//Get the processing level of the handler object
protected abstract int getHandleLevel();
//How to deal with each processor object
protected abstract void handle(AbstractRequest request);
}
public class Handler1 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 1;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler1 handle request:"+request.getRequestLevel());
}
}
public class Handler2 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 2;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler2 handle request:"+request.getRequestLevel());
}
}
public class Handler3 extends AbstractHandler {
@Override
protected int getHandleLevel() {
return 3;
}
@Override
protected void handle(AbstractRequest request) {
System.out.println("Handler3 handle request:"+request.getRequestLevel());
}
}
public class Request1 extends AbstractRequest {
public Request1(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 1;
}
}
public class Request2 extends AbstractRequest {
public Request2(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 2;
}
}
public class Request3 extends AbstractRequest {
public Request3(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 3;
}
}
public class Request4 extends AbstractRequest {
public Request4(Object object) {
super(object);
}
@Override
public int getRequestLevel() {
return 4;
}
}
public class Test {
public static void main(String args[]) {
AbstractHandler h1=new Handler1();
AbstractHandler h2=new Handler2();
AbstractHandler h3=new Handler3();
h1.nexthandler=h2;
h2.nexthandler=h3;
AbstractRequest r1=new Request1(h1);
AbstractRequest r2=new Request2(h2);
AbstractRequest r3=new Request3(h3);
AbstractRequest r4=new Request4(h3);
//Always initiate requests from the top of the chain
h1.handleRequest(r1);
h1.handleRequest(r2);
h1.handleRequest(r3);
h1.handleRequest(r4);
}
}
5. The Practical Application of Responsibility Chain Model in Android
A similar implementation of the responsibility chain model in Android source code is the distribution and processing of touch events. Whenever a user touches the screen, Android wraps the corresponding event into an event object that is distributed and delivered from top to bottom of the ViewTree. The recursive invocation of ViewGroup event delivery is similar to a chain of responsibility. Once the responsible person is found, the event will be held and consumed by the responsible person, which is embodied in the setting of the return value in the onTouchEvent method of View. If the onTouchEvent returns false, it means that the current View will not be a replicator of the event and will not hold it if it is true. Instead, the View holds the event and no longer passes it out.
View's Event Distribution Mechanism (Montion Event Distribution Process):
public boolean dispatchTouchEvent(MotionEvent ev)
If the event can be passed to the current View, then this method must be invoked.
public boolean onInterceptTouchEvent(MotionEvent ev)
Used to determine whether to intercept an event
public boolean onTouchEvent(MotionEvent ev)
Used to handle click events
Flow relationships (pseudocode)
public boolean dispatchTouchEvent(MotionEvent ev){
boolean consume=false;
if(onInterceptTouchEvent(ev)){
consume=onTouchEvent(ev);
}else{
consume=child.dispatchTouchEvent(ev);
}
return consume;
}