首页 > 代码库 > 揭开观察者设计模式的神秘面纱,手把手教你写监听器

揭开观察者设计模式的神秘面纱,手把手教你写监听器

我们在写代码的时候,遇到最常用的就是监听器了。那么实际中,我们也要进行事件的监听。而有些事件是业务逻辑需要实现的,跟随事物变化动态变化的。假如说我们要实现一个事件,有位置的监听,有颜色的监听,有坐标的监听,有速度的监听,那么这么多监听的事件。那么我们就需要这么多个监听器。这些监听器如何被管理呢。我们可以创造一个类似管理员身份的神秘角色,这个角色就是一个监听器池说一个监听器池,可以移除和增加监听器。当我们触发某一事件的时候,需要这些监听器全部执行监听。

现在我们来模拟一下按钮Button的实现。

新建一个点击事件的接口Clickable.java。只负责执行点击事件。

public interface Clickable {
    //点击事件
    void onClick();
}

新建一个按钮类MyButton并且实现点击事件接口Clickable,这样就要求我们实现onClick方法。

public class MyButton implements Clickable {
    @Override
    public void onClick() {
        //执行所有监听器里的方法,监听器1,监听器2 ...

    }
}  
那么此时,监听器又干什么了呢?我们都知道监听器都是接口对象。就相当于一个管理员。点击事件的接口对象就相当于一个事件。而事件的具体内容就通过方法onClick()来体现。

那么既然管理员管理事件,我们先创建管理员(监听器接口),然后管理事物( onClick() )。

监听器接口如下:

public interface OnClickListener {
    void onClick(Clickable clickable);
}

与此同时,我们需要增加监听器,写一个设置监听器的方法。对这个接口进行回调。


</pre><pre name="code" class="java">  public void setOnClickListener(OnClickListener onClickListener){
        if(onClickListener!=null){
            onClickListener.onClick(this);
        }
    }


这样的话,当我们设置监听的时候,从外部引入的OnClickListener接口对象不为空,就会执行OnClickListener接口中的onClick()方法。

接下来,我们可以实现这个监听器接口用来作为得到OnClickListener接口对象的方式。这个地方可能比较难理解。我们应该知道,如果一个类实现了某个接口,通过实例化这个类对象而得到相应的接口对象。

下面我们来新建一个颜色监听器。如果颜色改变,这里我默认为true。实际上这里可以进行颜色的判断。当发生变化的时候,我们需要向外界暴露一个方法,供外界调用,所以我们在类里面再新建一个抽象方法。当外部匿名构造这个类对象的时候同时也会实现这个类的方法。

 public static abstract  class OnColorListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                colorChanged();
            }
        }
        public  abstract void colorChanged();
    }

接下来我们再新建一个位置监听器。同样和上面一样,代码如下:

 public static abstract  class OnCoordinateListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                coordinateChanged();
            }
        }
        public  abstract void coordinateChanged();
    }

再接下来我们需要一个焦点监听器。同上,

    public static abstract  class OnFocusListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                onFocusChanged();
            }
        }
        public  abstract void onFocusChanged();
    }

这三个类实现了OnClickListener接口,那么我们只要匿名构造这三个对象便可以得到OnClickListener接口对象。同时也实现了OnclickListener里面的接口方法。在这个方法里面,我们分别进行了相应监听目的的变化监听。当某某发生改变的时候,我们就向外界提供一个方法,供调用者去实现。所以把这个类改成了抽象类,同时提供了抽象方法。外界如何调用的呢。我们可以看到setOnClickListener方法

  public void setOnClickListener(OnClickListener onClickListener){
        if(onClickListener!=null){
            onClickListener.onClick(this);
        }
    }

我们看到这里,我们便知道,传进来的OnClicklistener接口对象可以由它具体的实现类的匿名对象得到,也可以由它自身的接口对象得到。所以传进来的参数可以是以下几种


  • OnClickListener
  • FocusListener
  • OnCoordinateListener
  • OnColorListener
这几种的匿名对象。其实质是OnClickListener对象。为什么也可以传后面三个呢?

OnClickListener onClickListener = new FocusListener();
同时也可以
OnClickListener onClickListener() = new OnCoordinateListener();
或者其他两种的匿名对象也是可以的。

好了到目前为止,咱们的完整的代码是这样的。

public class Button implements Clickable{
    String color;
    int x,y;
    public void setOnClickListener(OnClickListener onClickListener){
        if(onClickListener!=null){
            onClickListener.onClick(this);
        }
    }

    @Override
    public void click() {
        //执行所有监听器操作
    }

    public interface OnClickListener{
        public void onClick(Clickable clickable);
    }

    public static abstract  class OnColorListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                colorChanged();
            }
        }
        public  abstract void colorChanged();
    }
    public static abstract  class OnCoordinateListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                coordinateChanged();
            }
        }
        public  abstract void coordinateChanged();
    }
    public static abstract  class OnFocusListener implements OnClickListener{

        @Override
        public void onClick(Clickable clickable) {
            if(true){
                onFocusChanged();
            }
        }
        public  abstract void onFocusChanged();
    }
}

上面的代码我估计大家都能看懂。接下来,我们就要对这几个监听器的接口对象进行管理了,我们可以分开管理也可以统一管理,如何分开管理这些接口对象呢?我们可以新建三个监听器的List集合对象。同时增加它的add和remove方法。但是我们没必要这样干,为什么呢?上面我解释过,匿名构造得到的OnColorListener对象或者OnCoordinateListener亦或者是OnFocusListener接口对象也好,其实质都是OnClickListener接口对象。所以我们只需要一个集合管理这些监听器就可以了。


  private static List<OnClickListener> onClickListeners =new ArrayList<OnClickListener>();
    
    
    private void addClickListener(OnClickListener onClickListener){
        onClickListeners.add(onClickListener);
    }
    
    
    private void remove(OnClickListener onClickListener){
        onClickListeners.remove(onClickListener);
    }

这样我们就可以自由得管理这些监听器了,我们知道当我们setOnClickListener的时候,新建一个OnClickListener匿名对象的时候,我们需要把它加入到池中,也就是这个list集合中。代码如下:

  public void setOnClickListener(OnClickListener onClickListener){
        if(onClickListener!=null){
            onClickListener.onClick(this);
        }
        addClickListener(onClickListener);
    }


ok。说了这么多,再来看看我们的此时的完整代码。


package com.example.chenlei.myapplication.widget;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by chenlei on 2016/10/24.
 */

public  class Button implements Clickable{
    String color;
    int x,y;
    public void setOnClickListener(OnClickListener onClickListener){
        if(onClickListener!=null){
            onClickListener.onClick(this);
        }
        addClickListener(onClickListener);
    }

    @Override
    public void click() {
        //执行所有监听器操作
    }

    public  interface OnClickListener{
        public void onClick(Button button);
    }
    private static List<OnClickListener> onClickListeners =new ArrayList<OnClickListener>();


    private void addClickListener(OnClickListener onClickListener){
        onClickListeners.add(onClickListener);
    }


    private void remove(OnClickListener onClickListener){
        onClickListeners.remove(onClickListener);
    }


    public static abstract  class OnColorListener implements  OnClickListener{

        @Override
        public void onClick(Button button) {
            if(true){
                colorChanged();
            }
        }
        public  abstract void colorChanged();
    }
    public static abstract  class OnCoordinateListener implements OnClickListener{

        @Override
        public void onClick(Button button) {
            if(true){
                coordinateChanged();
            }
        }
        public  abstract void coordinateChanged();
    }
    public static abstract  class OnFocusListener implements OnClickListener{

        @Override
        public void onClick(Button button) {
            if(true){
                onFocusChanged();
            }
        }
        public  abstract void onFocusChanged();
    }
}

如果我们需要执行所有被监听对象工作的时候,我们该怎么做呢?


  @Override
    public void click() {
        //执行所有监听器操作
        for(OnClickListener onClickListener :onClickListeners){
            onClickListener.onClick(this);
        }
    }


我们只需要遍历一下集合中的监听器就可以了。好了,那么接下来咱们看看怎么使用吧!

public class MainActivity extends AppCompatActivity {
    private TextView tx;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tx = (TextView) findViewById(R.id.tx);
        Button button =new Button();
        button.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(Button button1) {
                Log.e("TAG","我是回调方法");
            }
        });
        Button button1 =new Button();
        button1.setOnClickListener(new Button.OnColorListener() {
            @Override
            public void colorChanged() {
                Log.e("TAG","颜色改变后需要干神马");
            }
        });
        Button button2 =new Button();
        button2.setOnClickListener(new Button.OnCoordinateListener() {
            @Override
            public void coordinateChanged() {
                Log.e("TAG","坐标改变后需要干神马");
            }
        });
        Button button3 =new Button();
        button3.setOnClickListener(new Button.OnFocusListener() {
            @Override
            public void onFocusChanged() {
                Log.e("TAG","焦点改变后需要干神马");
            }
        });
    }

}


打印出的Log结果如下图:

技术分享


揭开观察者设计模式的神秘面纱,手把手教你写监听器