美文网首页Android大法好知识 | 解析Android
Android常用的设计模式<二>:观察者模式

Android常用的设计模式<二>:观察者模式

作者: JackMeGo | 来源:发表于2017-01-11 16:48 被阅读450次
    Observer

    在上一篇Android常用的设计模式<一>:Builder模式中,介绍了Builder设计模式,本文将介绍另一种常用的设计模式,观察者模式。观察者模式涉及到两个基本概念,观察者和事件,思路很简单,事件对象将所有关心该事件的观察者对象添加在自己维护的一个Vector容器中,完成注册,当事件被触发时,通知列表中的对象,这些对象依次执行自己的动作。

    通过调用回调函数也可以在事件被触发时完成不同的动作,他们的区别在于,回调函数的方式是一对一的方式,而观察者是一对多的方式。当一个事件对应多个观察者对象,或者需要动态添加或删除某个观察者对象时,无论在逻辑的理解上还是代码的清晰度上,观察者模式都要优于回调函数方式。

    Java对观察者模式的支持是通过Observable类和Observer接口实现的,事件通过继承Observable类实现对观察者的注册和解除注册功能,并在事件被触发时调用setChanged函数和notifyObservers函数通知观察者。

    给个具体的例子,定义一个地震警报事件(EarthQuakeAlert),有三个观察者关注这个事件,大学(CollegeObserver),科研机构(InstitutionObserver)以及市民(CitizenObserver)。

    首先定义EarthQuakeAlert:

    public class EarthQuakeAlert extends Observable {
        private String mLocation;
        private String mTime;
     
        public void setDetail(String time, String location) {
            mTime = time;
            mLocation = location;
      
            setChanged();
            notifyObservers(this);
        }
     
        public String getLocation() {
            return mLocation;
        }
     
        public String getTime() {
            return mTime;
        }
    }
    

    EarthQuakeAlert继承Observable,通过addObserver和deleteObserver添加或删除观察者,并在事件被触发时调用父类Observable的setChanged函数和notifyObservers函数通知所有的观察者。

    然后定义三个观察者:
    CollegeObserver.java

    public class CollegeObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            EarthQuakeAlert alert = (EarthQuakeAlert) o;
      
            String info = String.format("College received earthquake alert, location is %s, time is %s", 
            alert.getLocation(), alert.getTime());
            System.out.println(info);
        }
    }
    

    InstitutionObserver.java

    public class InstitutionObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            EarthQuakeAlert alert = (EarthQuakeAlert) o;
      
            String info = String.format("Institution received earthquake alert, location is %s, time is %s", 
            alert.getLocation(), alert.getTime());
            System.out.println(info);
        }
    }
    

    CitizenObserver.java

    public class CitizenObserver implements Observer {
        @Override
        public void update(Observable o, Object arg) {
            EarthQuakeAlert alert = (EarthQuakeAlert) o;
      
            String info = String.format("Citizens received earthquake alert, location is %s, time is %s", 
            alert.getLocation(), alert.getTime());
            System.out.println(info);
        }
    }
    

    使用过程如下:

    public class ObserverPatternDemo {
        public static void main(String[] args) {
            // 定义事件
            EarthQuakeAlert alert = new EarthQuakeAlert();
            // 定义三个观察者
            CollegeObserver collegeObserver = new CollegeObserver();
            InstitutionObserver institutionObserver = new InstitutionObserver();
            CitizenObserver citizenObserver = new CitizenObserver();
            // 添加三个观察者
            alert.addObserver(collegeObserver);
            alert.addObserver(institutionObserver);
            alert.addObserver(citizenObserver);
            // 触发事件
            alert.setDetail("2008-5-12", "SiChuan, China");
            // 删除一个观察者
            alert.deleteObserver(collegeObserver);
            // 触发事件
            alert.setDetail("2015-8-8", "Washington, USA");
        }
    }
    

    输出如下:

    Citizens received earthquake alert, location is SiChuan, China, time is 2008-5-12
    Institution received earthquake alert, location is SiChuan, China, time is 2008-5-12
    College received earthquake alert, location is SiChuan, China, time is 2008-5-12
    
    Citizens received earthquake alert, location is Washington, USA, time is 2015-8-8
    Institution received earthquake alert, location is Washington, USA, time is 2015-8-8
    

    我们看一下Observable和Observer代码,原理都比较简单。
    Observable类代码如下:

    public class Observable {
        private boolean changed = false;
        // Vector存放观察者
        private Vector<Observer> obs;
    
        public Observable() {
            obs = new Vector<>();
        }
        // 添加新的观察者
        public synchronized void addObserver(Observer o) {
            if (o == null)
                throw new NullPointerException();
            if (!obs.contains(o)) {
                obs.addElement(o);
            }
        }
        // 删除观察者
        public synchronized void deleteObserver(Observer o) {
            obs.removeElement(o);
        }
        // 通知事件发生,无参数
        public void notifyObservers() {
            notifyObservers(null);
        }
        // 通知事件发生,带参数
        public void notifyObservers(Object arg) {
            Object[] arrLocal;
    
            // 将所有观察者拷贝到一个临时数组里(快照),然后对该数组中的观察者执行update函数
            // 这样可以避免遍历Vector过程中有新的观察者加入或删除
            synchronized (this) {
                 if (!changed)
                    return;
                arrLocal = obs.toArray();
                clearChanged();
            }
            // 调用每个观察者的update方法
            for (int i = arrLocal.length-1; i>=0; i--)
                ((Observer)arrLocal[i]).update(this, arg);
        }
        // 删除所有观察者
        public synchronized void deleteObservers() {
            obs.removeAllElements();
        }
        // 设置标志位,否则notifyObservers不起作用
        protected synchronized void setChanged() {
            changed = true;
        }
        // 返回观察者数量
        public synchronized int countObservers() {
            return obs.size();
        }
    }
    

    Observer接口很简单,只有一个update函数,观察者实现这个函数,完成自己接收到事件后的操作。

    public interface Observer {
        void update(Observable o, Object arg);
    }
    

    观察者模式在android里面BroadCast,Eventbus等方面有所使用。

    相关文章

      网友评论

      本文标题:Android常用的设计模式<二>:观察者模式

      本文链接:https://www.haomeiwen.com/subject/ovdrbttx.html