• 通过Android View的两种事件响应方法比较inheritance和composition


    Android view有两种主要的处理事件的方式,

    1. 在View的子类中覆盖onXXX方法。因为这是在子类中通过覆盖的方式来响应事件,我称之为基于继承(inheritance)的响应方式。
    2. 调用View.setXXXListener,参数会实现View.OnXXXListener接口。因为View对象和Listner组合起来完成工作,我称之为基于组合(composition)的响应方式。

    例如对于touch事件而言,View.dispatchTouchEvent接收到touch事件对象,然后:

    1. 调用通过View.setOnTouchListener注册的listener。
    2. 调用可以被子类覆盖的onTouchEvent方法。

    举个简单例子,一个Activity中有一个edit框(EditText对象)。EditText是通过代码添加的到Activity中的。我希望在点击它时,自动把该框的底色设置为红色。

    如果采用第一种方式,其EditText的子类是:

    public class TouchChangeBackgroundColorEditText extends EditText {
    
        public MyEditText(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            this.setBackgroundColor(Color.RED);
            return super.onTouchEvent(event);
        }
    }

    然后我们在Activity中使用该EditText的子类。

    如果采用第二种方法,则需要创建一个对touch事件的listener:

    public class TouchChangeBackgroundColorListener implements View.OnTouchListener {
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.setBackgroundColor(Color.RED);
            return false;
        }
    }

    然后在Activity中使用普通EditText,并对该EditText调用setOnTouchListener(new TouchChangeBackgroundColorListener)。

    然后用户又想对某些EditText使用Key event来改变背景颜色,那如果采用基于继承的方式,用户需要创建KeyChangeBackGroundColorEditText的子类,在其中覆盖onKeyDown方法;如果采用组合的方式,则需要实现OnKeyListener并添加到EditText中。

    现在问题来了,用户希望某些EditText是不响应touch和key事件的,有些只响应一种,有些两种都响应。那么如果采用继承的方式,那需要四种对象,一个基本都EditText和三种针对only touch,only key和both touch and key的子类。

    但如果采用组合的方式,我们仍然只需要两个listener,只需对不同的EditText添加不同的listener即可。

    如果更复杂,我们还想针对trackball改变颜色,那如果采用继承,则可能有3×3=9种类。但采用组合,只需要三种listener,然后EditText根据需要添加即可。

    所以说,在可能有多种因素导致变化的时候,继承可能导致对象种类(即类)爆炸式增长;而组合可以用不同的对象封装不同的变化,减少类的个数。

    但这里减少的只是编码中类的个数,而在运行时如果采用继承,那对象的个数是EditText的个数;但如果采用组合,那每个EditText都对应着一个Listener,所以有更多的对象个数。所以说,组合一般较继承产生更多的运行时对象,这需要更多的内存(对象存储)和运算时间(对象间相互调用)。

    现在假设app的界面上已经有一个EditText控件,我们又想在app中通过选项来控制该EditText的行为,例如我们有三个选项,分别对应touch,key和trackball事件发生时是否改变该EditText的背景颜色。那么如果采用组合,可以先创建好三个listener,然后根据选择添加listener到现有的的EditText中。但如果使用继承,根本是无法动态改变其行为了。所以说,组合可以动态改变对象的行为,而继承只能在静态改变。

    再回到前面继承的onTouchEvent方法,在最后一行,我需要调用super.onTouchEvent。事实上,我开始实现时忘记调用这行了,结果点击edit框时,可以改变颜色,但无法切出输入法。在现实中覆盖父类的方法时,有的父类方法是需要在子类中被调用的,但有的却不需要。覆盖的时候要详细查看父类文档和代码。但如果采用组合的方式,我只需要关系listener自己的视线即可,并不需要调用view中跟touch处理相关的代码。所以说,继承是一种白盒复用,在覆盖父类的方法时,需要关心父类方法的实现;但组合是黑盒测试,我只需要实现接口即可,而不需要关心该接口如何被调用。

    故而Design pattern中所有模式的两大基石之一就是:Favor object composition over class inheritance。

  • 相关阅读:
    KVM虚拟化学习笔记系列文章列表(转)
    centos 6.5安装docker报错(查看报错详细信息--推荐)
    利用JMX统计远程JAVA进程的CPU和Memory---jVM managerment API
    OpenJDK和JDK区别
    docker sshd image problem, session required pam_loginuid.so, cann't login
    ssh-keygen
    优秀的软件测试人员必需具备的素质
    java基础篇---I/O技术
    jstl long类型数据转换为日期格式
    apache-hadoop-1.2.1、hbase、hive、mahout、nutch、solr安装教程
  • 原文地址:https://www.cnblogs.com/xichengtie/p/3533394.html
Copyright © 2020-2023  润新知