参考:http://droidyue.com/blog/2015/06/27/desgign-pattern-observer/index.html
http://www.cnblogs.com/mythou/p/3370340.html
一.定义
观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。
1.关键要素
主题
主题是观察者观察的对象,一个主题必须具备下面三个特征。
持有监听的观察者的引用
支持增加和删除观察者
主题状态改变,通知观察者
观察者
当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。
2.为什么要用这种模式
这里举一个例子来说明,牛奶送奶站就是主题,订奶客户为监听者,客户从送奶站订阅牛奶后,会每天收到牛奶。如果客户不想订阅了,可以取消,以后就不会收到牛奶。
松耦合
观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。
主题只负责通知观察者,但无需了解观察者如何处理通知。举个例子,送奶站只负责送递牛奶,不关心客户是喝掉还是洗脸。
观察者只需等待主题通知,无需观察主题相关的细节。还是那个例子,客户只需关心送奶站送到牛奶,不关心牛奶由哪个快递人员,使用何种交通工具送达。
通知不错过
由于被动接受,正常情况下不会错过主题的改变通知。而主动获取的话,由于时机选取问题,可能导致错过某些状态。
3.简单实现
在java中,提供了一快速实现观察者设计模式的方案。
java中提供了一个类Observable和一个接口Observer
Observer这个接口的源码是这样的:
public interface Observer { /** * This method is called if the specified {@code Observable} object's * {@code notifyObservers} method is called (because the {@code Observable} * object has been updated. * * @param observable * the {@link Observable} object. * @param data * the data passed to {@link Observable#notifyObservers(Object)}. */ void update(Observable observable, Object data); }
其中Obervable有以下的方法
public class Observable { List<Observer> observers = new ArrayList<Observer>(); boolean changed = false; /** * Constructs a new {@code Observable} object. */ public Observable() { } /** * Adds the specified observer to the list of observers. If it is already * registered, it is not added a second time. * * @param observer * the Observer to add. */ public void addObserver(Observer observer) { if (observer == null) { throw new NullPointerException("observer == null"); } synchronized (this) { if (!observers.contains(observer)) observers.add(observer); } } /** * Clears the changed flag for this {@code Observable}. After calling * {@code clearChanged()}, {@code hasChanged()} will return {@code false}. */ protected void clearChanged() { changed = false; } /** * Returns the number of observers registered to this {@code Observable}. * * @return the number of observers. */ public int countObservers() { return observers.size(); } /** * Removes the specified observer from the list of observers. Passing null * won't do anything. * * @param observer * the observer to remove. */ public synchronized void deleteObserver(Observer observer) { observers.remove(observer); } /** * Removes all observers from the list of observers. */ public synchronized void deleteObservers() { observers.clear(); } /** * Returns the changed flag for this {@code Observable}. * * @return {@code true} when the changed flag for this {@code Observable} is * set, {@code false} otherwise. */ public boolean hasChanged() { return changed; } /** * If {@code hasChanged()} returns {@code true}, calls the {@code update()} * method for every observer in the list of observers using null as the * argument. Afterwards, calls {@code clearChanged()}. * <p> * Equivalent to calling {@code notifyObservers(null)}. */ public void notifyObservers() { notifyObservers(null); } /** * If {@code hasChanged()} returns {@code true}, calls the {@code update()} * method for every Observer in the list of observers using the specified * argument. Afterwards calls {@code clearChanged()}. * * @param data * the argument passed to {@code update()}. */ @SuppressWarnings("unchecked") public void notifyObservers(Object data) { int size = 0; Observer[] arrays = null; synchronized (this) { if (hasChanged()) { clearChanged(); size = observers.size(); arrays = new Observer[size]; observers.toArray(arrays); } } if (arrays != null) { for (Observer observer : arrays) { observer.update(this, data); } } } /** * Sets the changed flag for this {@code Observable}. After calling * {@code setChanged()}, {@code hasChanged()} will return {@code true}. */ protected void setChanged() { changed = true; } }举个例子: 老师宣布现在到点了,可以去吃饭了,然后同学们收到这个消息后都下课吃饭去了
明显老师的观察对象,儿同学们是观察者
老师类
public class Teacher extends Observable { public void sayMessage(String str){ setChanged(); //必不可少的方法 notifyObservers(str); } }学生类 学生1
public class Student1 implements Observer { @Override public void update(Observable observable, Object data) { Teacher teacher = (Teacher) observable; String something = (String) data; Log.e("Student1",observable+"说:"+something); } }学生2
public class Student2 implements Observer { @Override public void update(Observable observable, Object data) { Teacher teacher = (Teacher) observable; String something = (String) data; Log.e("Student2",teacher+"说:"+something); } }
主函数里的写法:
Teacher teacher = new Teacher(); Student1 student1 = new Student1(); Student2 student2 = new Student2(); teacher.addObserver(student1); teacher.addObserver(student2); teacher.sayMessage("到点了,可以吃饭了");运行结果:
E/Student1: ObverserPatterm.Teacher@39d87068说:到点了,可以吃饭了
E/Student2: ObverserPatterm.Teacher@39d87068说:到点了,可以吃饭了
在java里面可以使用这种现成方式去实现观察者模式,但是这个方法放在android上有缺陷。因为java里面是单继承多实现,android里面组件需要继承父类组件,比如一般的控件都要继承view、viewGroup本身或者子类,如果Teacher继承了Observable 那么他将不能再继承其他类了,那这个类功能就太单一了。
这个时候我们要需要自定义观察者设计模式
我们模仿类Observable,给发布者添加上面三种方法
学生接口类的实现public class Teacher { //1.定义接口,接口方法 public interface MessageObserver{ public void onMessageChanged(String message); } //2.定义集合放置我们的接口对象 private List<MessageObserver> messageObservers = new ArrayList<MessageObserver>(); //我们模仿类Observable,给发布者添加上面三种方法,代码改成 //添加观察者 public void addObserver(MessageObserver mObserver){ if (mObserver ==null){ throw new NullPointerException("mObserver ==null"); } synchronized (this){ if (!messageObservers.contains(mObserver)){ messageObservers.add(mObserver); } } } //删除观察者 public void deleteObserver(MessageObserver mObserver){ messageObservers.remove(mObserver); } //数据更新 public void noticeMessage(String message){ for (MessageObserver o:messageObservers){ o.onMessageChanged(message); } } }
public class Student1 implements Teacher.MessageObserver{ @Override public void onMessageChanged(String message) { Log.e("student1","获取到的消息:"+message); } }测试方法
Teacher teacher = new Teacher(); Student1 student1 = new Student1(); Student2 student2 = new Student2(); teacher.addObserver(student1); teacher.addObserver(student2); teacher.noticeMessage("到点了12点了,可以吃饭了");
4、Android 应用开发中的观察者模式
在我们做Android应用的时候,会大量使用观察者模式,因为Framework层里面的事件驱动都是基于观察者模式实现的。另外在Framework层里面的各种服务在数据变更的时候,也是通过观察者模式实现上层数据更新。下面会讲两个例子来说明:
1.控件中Listener监听方式
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } });例如上面的代码,注册了一个按钮的监听方法。这里实际上是应用了一对一的观察者模式,setOnClickListener()方法就是注册一个观察者,Button对象就是我们要观察的目标对象。而new出来的OnClickListener(),就是我们实际的观察者。
每当我们的目标按钮对象被点击,状态发生变化的时候,就会通过回调注册的OnClickListener观察者的onClick方法会来通知观察者,Button状态发生变化。这里的onClick相当于前面例子里面的update方法。
public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); }参考自:http://blog.qiji.tech/archives/2966