从 Android 源码 发现设计模式
前面已经写过了事件的分发机制,以及源码的分析了。每当用户接触到了屏幕的时候,Android会将对应的事件包装成一个事件从对象ViewTree的顶部从上到下的开始分发传递。而在ViewGroup中,ViewGroup中执行事件的派发分发是通过dispatchTouchEvent。
在这个方法中,我们可以很清楚的看到ViewGroup就会遍历所有的子View。拿到子View的时候,源码中做了几个判断,判断这个子View是否符合条件。如果不满足则直接选取下一个子View。 拿到符合条件的子View,那么将调用 dispatchTransformedTouchEvent 这个方法。 在dispatchTransformedTouchEvent方法中就调用了child.dispatchTouchEvent(event)。
从上源码中可以的知到最重要的一点就是,ViewGroup的事件投递的递归调用就类似一个责任链,不断的从子View中寻找能处理这个事件的子View,一旦找到了这个责任者,那么将由这个责任者持有并且消费这个事件。从View中的 onTouchEvent 方法的返回值可以很清楚的看到这一点,当onTouchEvent 返回 false 代表 ,那么意味着这个不是该事件的负责人,当返回了true,此时会持有这个事件,并不向外再传递了。
责任链模式 介绍
从ViewGroup对于事件的分发来说,一个传递给一个,形成了一个链子,最后从链子中找到一个来处理这个事件。把这种形式抽象出来,其实就是责任链模式,我们把多个节点首尾相连所构成的模式称为链。对于这种构成,把每一个节点都看做一个对象,每个对象拥有不同的处理逻辑,然后将一个责任从链子的首端出发,沿着链子依次传递给每个节点的对象,直到有个对象处理这个责任。
责任链模式 定义
使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理他为止。
责任链模式 使用场景
使用场景就和ViewGroup一样,多个对象处理一个请求,但是具体由哪个对象处理,是动态决定的。
责任链模式 UML类图
从上面的类图我们可以看到的一点就是,因为在责任链中的请求和对应的处理规则都是不尽相同的,在这种情况的状态下,就要把请求类和处理规则进行了封装,封装到一个独立的对象,那么同样从链子的首端开始处理分发,不同的请求也会找到相应的处理规则来处理请求。
用例子来说明
抽象请求者
public abstract class AbstractRequest {
private Object obj ;
public AbstractRequest(Object obj){
this.obj = obj;
}
public Object getContent(){
return obj;
}
public abstract int getRequestLevel();
}
抽象处理者
public abstract class AbstractHandler {
private AbstractHandler nextHandler;
public void handleRequest(AbstractRequest request){
if(request.getRequestLevel() == getHandleLevel()){
handle(request);
}else{
if(nextHandler != null){
nextHandler.handleRequest(request);
}else{
System.out.println("这个请求没有相对应的 Handler 来处理");
}
}
}
public void setNextHandler(AbstractHandler nextHandler){
this.nextHandler = nextHandler;
}
protected abstract void handle(AbstractRequest request) ;
protected abstract int getHandleLevel();
}
请求者
public class Request_1 extends AbstractRequest{
public Request_1(Object obj) {
super(obj);
}
@Override
public int getRequestLevel() {
return 1;
}
}
public class Request_2 extends AbstractRequest{
public Request_2(Object obj) {
super(obj);
}
@Override
public int getRequestLevel() {
return 2;
}
}
public class Request_3 extends AbstractRequest{
public Request_3(Object obj) {
super(obj);
}
@Override
public int getRequestLevel() {
return 3;
}
}
处理者
public class Handler_1 extends AbstractHandler {
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理 request 的等级为 : " +request.getRequestLevel() );
}
@Override
protected int getHandleLevel() {
return 1;
}
}
public class Handler_2 extends AbstractHandler {
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理 request 的等级为 : " +request.getRequestLevel() );
}
@Override
protected int getHandleLevel() {
return 2;
}
}
public class Handler_3 extends AbstractHandler {
@Override
protected void handle(AbstractRequest request) {
System.out.println("处理 request 的等级为 : " +request.getRequestLevel() );
}
@Override
protected int getHandleLevel() {
return 3;
}
}
执行
public static void main(String[] args) {
AbstractHandler handler_1 = new Handler_1 () ;
AbstractHandler handler_2 = new Handler_2 () ;
AbstractHandler handler_3 = new Handler_3 () ;
//连成责任链
handler_1.setNextHandler(handler_2);
handler_2.setNextHandler(handler_3);
AbstractRequest request_1 = new Request_1("Request_1");
AbstractRequest request_2 = new Request_2("Request_2");
AbstractRequest request_3 = new Request_3("Request_3");
//都是从首端开始传送请求
handler_1.handleRequest(request_1);
handler_1.handleRequest(request_2);
handler_1.handleRequest(request_3);
}
运行结果
处理 request 的等级为 : 1
处理 request 的等级为 : 2
处理 request 的等级为 : 3
总结
责任链模式:
优点:显而易见,可以对链中请求者和处理者关系解耦,提高了代码的灵活性。
缺点:每次处理都要从头开始遍历,如果处理者太多牌,那么遍历必然会影响性能。