简介

观察者设计模式一个比较典型的例子是点击监听器 OnClickListener:对设置OnClickListener来说, View是被观察者,OnClickListener是观察者,二者通过setOnClickListener()方法达成订阅关系。订阅之后用户点击按钮的瞬间,系统就会将点击事件发送给已经注册的OnClickListener。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。当然,这也得益于我们可以随意定制自己程序中的观察者和被观察者,而警察叔叔明显无法要求小偷"你在作案的时候务必通知我"。OnClickListener的模式大致如下图20.30所示:

mousemove长按监听 简书 按钮监听事件_sed


如上图所示,通过setOnClickListener()方法,Button持有OnClickListener的引用。当用户点击按钮时,Button自动调用OnClickListener的onClick()方法。另外,如果把这张图中的概念抽象出来(Button:被观察者、OnClickListener:观察者、setOnClickListener() :订阅,onClick():事件),就由专用的观察者模式(例如只用于监听控件点击)转变成了通用的观察者模式,如下图20.31所示:

mousemove长按监听 简书 按钮监听事件_sed_02

示例:模拟按钮单击。

实现步骤:

  1. 写一个监听器接口,抽象出观察者的动作;
    注此时可以提供一个事件类来来描述事件的具体信息,让这个事件类作为监听器接口方法的参数,以便在主题对象和观察者之间传递数据。之所以抽取出事件类,是因为观察者在处理事件时它有可能要了解事情发生时的一些具体的状况。
  2. 每一个观察者对象类都实现上述的监听器接口;
  3. 主题对象
    a) 定义一个监听器类型的List列表,并提供相应的add方法
    b) 当主题对象状态发生变化时,依次调用List中的每一个观察者

第一步:定义描述事件的类,具体代码如下:

class ActionEvent {
    long when;  //事件发生的时间
    Object source;  //事件源
    public ActionEvent(long when, Object source) {
        this.when = when;
        this.source = source;
    }
    public long getWhen() {
        return when; 
    }
    public Object getSource() {
        return source; 
    }
}

第二步:定义抽象观察者接口,具体代码如下:

interface ActionListener {
    void actionPerformed(ActionEvent e);
}

第三步:定义具体观察者,具体代码如下:

class MyActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("button pressed!");
    }
}
class MyActionListener2 implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("button pressed 2!");
    }
}
class MyActionListener3 implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        System.out.println("button pressed 3!");
        System.out.println(e.getSource());
        System.out.println(e.getWhen());
    }
}

第四步:定义具体被观察者,具体代码如下:

class Button {
    private List<ActionListener> listeners = new ArrayList<ActionListener>();
    public void addActionListener(ActionListener listener) {
        listeners.add(listener);
    }
    public void buttonPressed() {
        ActionEvent e = new ActionEvent(System.currentTimeMillis(), this); 
        for (ActionListener listener : listeners) {
            listener.actionPerformed(e);
        }
    }
}

第五步:定义测试方法,具体代码如下:

public static void main(String[] args) {
    Button b = new Button();
    b.addActionListener(new MyActionListener());
    b.addActionListener(new MyActionListener2());
    b.addActionListener(new MyActionListener3());
    b.buttonPressed();
}

运行程序,结果如下图所示:

mousemove长按监听 简书 按钮监听事件_mousemove长按监听 简书_03