原文链接
1、概述
- 观察者模式定义了对象之间的一对多依赖关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。
- 在这里,发生改变的对象称之为观察目标,而被通知的对象称之为观察者。一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,所以么可以根据需要增加和删除观察者,使得系统更易于扩展。所以观察者提供了一种对象设计,让主题和观察者之间以松耦合的方式结合。
![在这里插入图片描述](https://img-blog.csdnimg.cn/462ae6880fda46c5bd09317c3a10e87f.png)
- 观察者模式包含如下角色:
- Subject: 目标
- ConcreteSubject: 具体目标
- Observer: 观察者
- ConcreteObserver: 具体观察者
2、代码例子
- 实现一个植物(目标)开花后会通知昆虫(观察者)来采蜜,关闭后昆虫回家的例子
- Observer
package com.company;
public interface Insect {
void work();
void home();
}
package com.company;
public class Bee implements Insect {
private int id;
public Bee(int id) {
this.id = id;
}
@Override
public void work() {
System.out.println("蜜蜂" + id + "工作");
}
@Override
public void home() {
System.out.println("蜜蜂" + id + "回家");
}
}
package com.company;
public interface Plant {
void registerInsect(Insect insect);
void unregisterInsect(Insect insect);
void notifyInsect(boolean isOpen);
}
package com.company;
import java.util.ArrayList;
import java.util.List;
public class Flower implements Plant {
private List<Insect> insects = new ArrayList<>();
@Override
public void registerInsect(Insect insect) {
insects.add(insect);
}
@Override
public void unregisterInsect(Insect insect) {
insects.remove(insect);
}
@Override
public void notifyInsect(boolean isOpen) {
for (int i = 0; i < insects.size(); i++) {
if (isOpen){
insects.get(i).work();
} else {
insects.get(i).home();
}
}
}
}
package com.company;
public class Main {
public static void main(String[] args) {
Plant flower = new Flower();
Insect 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对象,可以使用观察者模式创建一种链式触发机制。
3、Android自带的观察者
3-1、观察者Observer源码
public interface Observer {
void update(Observable o, Object arg);
}
3-2、被观察者Observable源码
public class Observable {
private boolean changed = false;
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;
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();
}
}
4、观察者模式的推\拉模型
- 推拉模型本质区别只是在于update传入的参数是一个属性还是对象本身
- 推模型是假定被观察者知道观察者需要的数据
- 拉模型是被观察者 不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值
- 优缺点
- 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;
- 而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要
4-1、推模型
package 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;
}
@Override
public void update(Observable o, Object arg) {
if ((Boolean)arg){
System.out.println("update: true"+id);
} else {
System.out.println("update: false"+id);
}
}
}
public class Flower extends Observable {
public void notifyInsect(boolean isOpen){
this.setChanged();
this.notifyObservers(isOpen);
}
}
Flower flower = new Flower();
Bee 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、拉模型
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);
}
}
package 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;
}
@Override
public 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);
}
}
}