java 设计模式:责任链模式与Android事件传递
1、概念
是一个请求有多个对象来处理,这些对象是一条链,但具体由哪个对象来处理,根据条件判断来确定,如果不能处理会传递给该链中的下一个对象,直到有对象处理它为止。
2、使用场景
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态制定一组对象处理请求,客户端可以动态创建职责链来处理请求。
3、uml结构分析
4、实际代码分析
/**
* 抽象请假审批类
*/
public abstract class Handler {
public int maxDay;
private Handler nextHandler;
public Handler(int maxDay) {
this.maxDay = maxDay;
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public void handlerRequest(int day){
if(day <= maxDay){
reply(day);
} else{
if(nextHandler != null){
nextHandler.handlerRequest(day);
}else {
System.out.println("没有跟高的领导审批了");
}
}
}
protected abstract void reply(int day);
}
/**
* 技术主管审批类
*/
public class Handler1 extends Handler {
public Handler1() {
super(10);
}
@Override
protected void reply(int day) {
System.out.print(day+"天请假,技术主管直接通过");
}
}
* 项目经理审批类
*/
public class Handler2 extends Handler {
public Handler2() {
super(5);
}
@Override
protected void reply(int day) {
System.out.print(day+"天请假,项目经历直接通过");
}
}
//代码运行
Handler2 handler2 = new Handler2();
handler2.setNextHandler(new Handler1());
handler2.handlerRequest(3);
在java中的实际运用,try-cache语句
在android 中发布有序广播 ordered broadcast,viewGroup/view 事件传递
优点与缺点
责任链模式是一种对象行为型模式,其主要优点如下。
- 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
- 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
- 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
其主要缺点如下。
- 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
- 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
- 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
viewGroup/view 事件传递
1)主要概念
MotionEvent 事件分发的基本操作,所有事件都是MotionEvent,对MotionEvent操作。
主要有三种操作 ACTION_DOWN/ACTION_MOVE/ACTION_UP
三个方法
dispatchTouchEvent 当有事件传递给view的时候,view就会调用该方法。这个返回值为boolean,返回告诉系统是否消耗了该事件。true为消耗,不会继续向下分发
onIntereptTouchEvent 拦截事件,只存在于viewgroup,view(存在于view树的最底层,没必要拦截了)中没有拦截事件。如果当前view 成功拦截这个事件,则要返回true,默认为false
onTouchEvent 具体处理整个事件逻辑的,对于他的返回结果就是是否消耗当前事件,如果不消耗当前事件的话,对于同一个事件,当前view就不会再接到这个事件。
总结:如果当前view可以处理就拦截处理,如果不可以,就交给子view
事件处理顺序
Activity -> PhoneWindow ->RootView ->ViewGroup ->View
2)viewgroup的事件分发
流程:
- 判断自身是否需要
- 自身不需要或者不确定,询问childview
- 如果子childview 不需要则调用自身的onTouchEvent
3)view的事件分发
view为啥会有dispatchTouchEvent方法?view可以注册很多事件监听器,可以进行事件分发
- 单机事件(onClickListener)
- 长按事件(onLongClickListener)
- 触摸事件(onTouchListener)
- View自身处理(onTouchEvent)
事件调用顺序:onTouchListener>onTouchEvent>onLongClickListener>onClickListener