1、概述
- 观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。
- 在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。所以观察者提供了一种对象设计,让主题和观察者之间以松耦合的方式结合。

观察者模式包含如下角色:
实现一个植物(目标)开花后会通知昆虫(观察者)来采蜜,关闭后昆虫回家的例子
- Observer ```html package com.company;
public interface Insect { void work(); void home(); }
- ConcreteObserver```htmlpackage com.company;public class Bee implements Insect {private int id;public Bee(int id) {this.id = id;}@Overridepublic void work() {System.out.println("蜜蜂" + id + "工作");}@Overridepublic void home() {System.out.println("蜜蜂" + id + "回家");}}
- Subject ```java package com.company;
public interface Plant { void registerInsect(Insect insect); void unregisterInsect(Insect insect); void notifyInsect(boolean isOpen); }
- ConcreteSubject```javapackage com.company;import java.util.ArrayList;import java.util.List;public class Flower implements Plant {private List<Insect> insects = new ArrayList<>();@Overridepublic void registerInsect(Insect insect) {insects.add(insect);}@Overridepublic void unregisterInsect(Insect insect) {insects.remove(insect);}@Overridepublic void notifyInsect(boolean isOpen) {for (int i = 0; i < insects.size(); i++) {if (isOpen){insects.get(i).work();} else {insects.get(i).home();}}}}
- 测试 ```java package com.company;
public class Main {
public static void main(String[] args) {// 一个SubjectPlant flower = new Flower();// 多个ObserveInsect insect1 = new Bee(1);Insect insect2 = new Bee(2);Insect insect3 = new Bee(3);flower.registerInsect(insect1);flower.registerInsect(insect2);flower.registerInsect(insect3);flower.notifyInsect(true);flower.notifyInsect(false);flower.unregisterInsect(insect1);flower.unregisterInsect(insect2);flower.unregisterInsect(insect3);}
}
- 主要思路:Subject提供注册(添加Observer)、注销(移除Observer)、通知(当Subject发生某种变化后,调用notify方法,通知所有的Observer对象)- RxJava的是拓展的观察者模式,A对象的行为影响B对象,B对象影响C对象,可以使用观察者模式创建一种链式触发机制。<a name="QhAUR"></a>## 3、Android自带的观察者<a name="qRQNa"></a>### 3-1、观察者Observer源码- 位于java.util目录下```jsonpublic interface Observer {void update(Observable o, Object arg);}
3-2、被观察者Observable源码
位于java.util目录下 ```json public class Observable {
/**
被观察者的数据是否改变 */
private boolean changed = false;/**
保存观察者的集合 */
private Vectorobs; 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);}/*** 通知观察者,hasChanged为true才真真通知观察者*/public void notifyObservers(Object arg) {Object[] arrLocal;synchronized (this) {if (!hasChanged())return;arrLocal = obs.toArray();clearChanged();}for (int i = arrLocal.length-1; i>=0; i--)((Observer)arrLocal[i]).update(this, arg);}public synchronized void deleteObservers() {obs.removeAllElements();}protected synchronized void setChanged() {changed = true;}protected synchronized void clearChanged() {changed = false;}public synchronized boolean hasChanged() {return changed;}/*** 观察者数量*/public synchronized int countObservers() {return obs.size();}
}
<a name="ZvwrQ"></a>## 4、观察者模式的推\拉模型- 推拉模型本质区别只是在于update传入的参数是一个属性还是对象本身- 推模型是假定被观察者知道观察者需要的数据- 拉模型是被观察者 不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值- 优缺点- 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;- 而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要<a name="eHKDJ"></a>### 4-1、推模型- Observer:观察者```javapackage com.xinhe.testandroid.observe;import java.util.Observable;import java.util.Observer;public class Bee implements Observer {private static final String TAG = "Bee";private int id;public Bee(int id) {this.id = id;}@Overridepublic void update(Observable o, Object arg) {if ((Boolean)arg){System.out.println("update: true"+id);} else {System.out.println("update: false"+id);}}}
Observable:被观察者
public class Flower extends Observable {public void notifyInsect(boolean isOpen){// 通知改变this.setChanged();// 通知所有观察者this.notifyObservers(isOpen);}}
验证
// 一个SubjectFlower flower = new Flower();// 多个ObserveBee insect1 = new Bee(1);Bee insect2 = new Bee(2);Bee insect3 = new Bee(3);flower.addObserver(insect1);flower.addObserver(insect2);flower.addObserver(insect3);flower.notifyInsect(true);flower.notifyInsect(false);flower.deleteObserver(insect1);flower.deleteObserver(insect2);flower.deleteObserver(insect3);
4-2、拉模型
再写个拉模型例子 ```java package com.xinhe.testandroid.observe;
import java.util.Observable;
public class Flower extends Observable {
private boolean isOpen;public boolean getOpen(){return isOpen;}public void notifyInsect(boolean isOpen){this.isOpen = isOpen;// 通知改变this.setChanged();// 通知所有观察者this.notifyObservers(this);}
}
- Bee```javapackage com.xinhe.testandroid.observe;import java.util.Observable;import java.util.Observer;public class Bee implements Observer {private static final String TAG = "Bee";private int id;public Bee(int id) {this.id = id;}@Overridepublic void update(Observable o, Object arg) {Flower flower = (Flower) arg;if (flower.getOpen()){System.out.println("update: true"+id);} else {System.out.println("update: false"+id);}}}
