1、概述

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

1、观察者模式 - 图1

  • 观察者模式包含如下角色:

    • Subject: 目标
    • ConcreteSubject: 具体目标
    • Observer: 观察者
    • ConcreteObserver: 具体观察者

      2、代码例子

  • 实现一个植物(目标)开花后会通知昆虫(观察者)来采蜜,关闭后昆虫回家的例子

  • Observer ```html package com.company;

public interface Insect { void work(); void home(); }

  1. - ConcreteObserver
  2. ```html
  3. package com.company;
  4. public class Bee implements Insect {
  5. private int id;
  6. public Bee(int id) {
  7. this.id = id;
  8. }
  9. @Override
  10. public void work() {
  11. System.out.println("蜜蜂" + id + "工作");
  12. }
  13. @Override
  14. public void home() {
  15. System.out.println("蜜蜂" + id + "回家");
  16. }
  17. }
  • Subject ```java package com.company;

public interface Plant { void registerInsect(Insect insect); void unregisterInsect(Insect insect); void notifyInsect(boolean isOpen); }

  1. - ConcreteSubject
  2. ```java
  3. package com.company;
  4. import java.util.ArrayList;
  5. import java.util.List;
  6. public class Flower implements Plant {
  7. private List<Insect> insects = new ArrayList<>();
  8. @Override
  9. public void registerInsect(Insect insect) {
  10. insects.add(insect);
  11. }
  12. @Override
  13. public void unregisterInsect(Insect insect) {
  14. insects.remove(insect);
  15. }
  16. @Override
  17. public void notifyInsect(boolean isOpen) {
  18. for (int i = 0; i < insects.size(); i++) {
  19. if (isOpen){
  20. insects.get(i).work();
  21. } else {
  22. insects.get(i).home();
  23. }
  24. }
  25. }
  26. }
  • 测试 ```java package com.company;

public class Main {

  1. public static void main(String[] args) {
  2. // 一个Subject
  3. Plant flower = new Flower();
  4. // 多个Observe
  5. Insect insect1 = new Bee(1);
  6. Insect insect2 = new Bee(2);
  7. Insect insect3 = new Bee(3);
  8. flower.registerInsect(insect1);
  9. flower.registerInsect(insect2);
  10. flower.registerInsect(insect3);
  11. flower.notifyInsect(true);
  12. flower.notifyInsect(false);
  13. flower.unregisterInsect(insect1);
  14. flower.unregisterInsect(insect2);
  15. flower.unregisterInsect(insect3);
  16. }

}

  1. - 主要思路:Subject提供注册(添加Observer)、注销(移除Observer)、通知(当Subject发生某种变化后,调用notify方法,通知所有的Observer对象)
  2. - RxJava的是拓展的观察者模式,A对象的行为影响B对象,B对象影响C对象,可以使用观察者模式创建一种链式触发机制。
  3. <a name="QhAUR"></a>
  4. ## 3、Android自带的观察者
  5. <a name="qRQNa"></a>
  6. ### 3-1、观察者Observer源码
  7. - 位于java.util目录下
  8. ```json
  9. public interface Observer {
  10. void update(Observable o, Object arg);
  11. }

3-2、被观察者Observable源码

  • 位于java.util目录下 ```json public class Observable {

    /**

    • 被观察者的数据是否改变 */
      private boolean changed = false;

      /**

    • 保存观察者的集合 */
      private Vector obs;

      public Observable() { obs = new Vector<>(); }

      /**

    • 添加观察者 */
      public synchronized void addObserver(Observer o) { if (o == null)

      1. throw new NullPointerException();

      if (!obs.contains(o)) {

      1. obs.addElement(o);

      } }

      /**

    • 删除观察者 */
      public synchronized void deleteObserver(Observer o) { obs.removeElement(o); }
  1. public void notifyObservers() {
  2. notifyObservers(null);
  3. }
  4. /**
  5. * 通知观察者,hasChanged为true才真真通知观察者
  6. */
  7. public void notifyObservers(Object arg) {
  8. Object[] arrLocal;
  9. synchronized (this) {
  10. if (!hasChanged())
  11. return;
  12. arrLocal = obs.toArray();
  13. clearChanged();
  14. }
  15. for (int i = arrLocal.length-1; i>=0; i--)
  16. ((Observer)arrLocal[i]).update(this, arg);
  17. }
  18. public synchronized void deleteObservers() {
  19. obs.removeAllElements();
  20. }
  21. protected synchronized void setChanged() {
  22. changed = true;
  23. }
  24. protected synchronized void clearChanged() {
  25. changed = false;
  26. }
  27. public synchronized boolean hasChanged() {
  28. return changed;
  29. }
  30. /**
  31. * 观察者数量
  32. */
  33. public synchronized int countObservers() {
  34. return obs.size();
  35. }

}

  1. <a name="ZvwrQ"></a>
  2. ## 4、观察者模式的推\拉模型
  3. - 推拉模型本质区别只是在于update传入的参数是一个属性还是对象本身
  4. - 推模型是假定被观察者知道观察者需要的数据
  5. - 拉模型是被观察者 不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值
  6. - 优缺点
  7. - 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;
  8. - 而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是主题对象本身,这基本上是主题对象能传递的最大数据集合了,基本上可以适应各种情况的需要
  9. <a name="eHKDJ"></a>
  10. ### 4-1、推模型
  11. - Observer:观察者
  12. ```java
  13. package com.xinhe.testandroid.observe;
  14. import java.util.Observable;
  15. import java.util.Observer;
  16. public class Bee implements Observer {
  17. private static final String TAG = "Bee";
  18. private int id;
  19. public Bee(int id) {
  20. this.id = id;
  21. }
  22. @Override
  23. public void update(Observable o, Object arg) {
  24. if ((Boolean)arg){
  25. System.out.println("update: true"+id);
  26. } else {
  27. System.out.println("update: false"+id);
  28. }
  29. }
  30. }
  • Observable:被观察者

    1. public class Flower extends Observable {
    2. public void notifyInsect(boolean isOpen){
    3. // 通知改变
    4. this.setChanged();
    5. // 通知所有观察者
    6. this.notifyObservers(isOpen);
    7. }
    8. }
  • 验证

    1. // 一个Subject
    2. Flower flower = new Flower();
    3. // 多个Observe
    4. Bee insect1 = new Bee(1);
    5. Bee insect2 = new Bee(2);
    6. Bee insect3 = new Bee(3);
    7. flower.addObserver(insect1);
    8. flower.addObserver(insect2);
    9. flower.addObserver(insect3);
    10. flower.notifyInsect(true);
    11. flower.notifyInsect(false);
    12. flower.deleteObserver(insect1);
    13. flower.deleteObserver(insect2);
    14. flower.deleteObserver(insect3);

    4-2、拉模型

  • 再写个拉模型例子 ```java package com.xinhe.testandroid.observe;

import java.util.Observable;

public class Flower extends Observable {

  1. private boolean isOpen;
  2. public boolean getOpen(){
  3. return isOpen;
  4. }
  5. public void notifyInsect(boolean isOpen){
  6. this.isOpen = isOpen;
  7. // 通知改变
  8. this.setChanged();
  9. // 通知所有观察者
  10. this.notifyObservers(this);
  11. }

}

  1. - Bee
  2. ```java
  3. package com.xinhe.testandroid.observe;
  4. import java.util.Observable;
  5. import java.util.Observer;
  6. public class Bee implements Observer {
  7. private static final String TAG = "Bee";
  8. private int id;
  9. public Bee(int id) {
  10. this.id = id;
  11. }
  12. @Override
  13. public void update(Observable o, Object arg) {
  14. Flower flower = (Flower) arg;
  15. if (flower.getOpen()){
  16. System.out.println("update: true"+id);
  17. } else {
  18. System.out.println("update: false"+id);
  19. }
  20. }
  21. }