当对象间存在一对多关系时,则使用观察者模式。比如,当一个对象被修改时,则会自动通知它的依赖对,观察者模式属于行为型模式。

场景

  • 关联行为场景,一个对象的改变将导致其他一个或多个对象也发生改变
  • 事件多级触发场景,A对象的行为将影响B对象,B对象的行为将影响C对象……
  • 跨系统的消息交换场景,如消息队列、事件总线的处理机制

实现

观察者模式核心就一个点,用一个list把观察者保存起来,并提供add和remove观察者,在被观察者变化的时候就遍历并调用list里观察者的方法,核心就是一个list遍历。

观察者模式使用三个类 Subject、Observer 和 Client

Subject

  1. public class Subject {
  2. @Override
  3. public void registerObservers(Observer observer) {
  4. observers.add(observer);
  5. }
  6. @Override
  7. public void unRegisterObservers(Observer observer) {
  8. observers.remove(observer);
  9. }
  10. @Override
  11. public void notifyObservers(String content) {
  12. for (Observer observer : observers) {
  13. observer.update(content);
  14. }
  15. }
  16. }

Observer

  1. public interface Observer {
  2. /**
  3. * 用于更新自身的方法
  4. * @param content 更新的内容
  5. */
  6. void update(String content);
  7. }
  1. public class Coder implements Observer {
  2. private String mName;
  3. public Coder(String name) {
  4. mName = name;
  5. }
  6. @Override
  7. public void update(String content) {
  8. System.out.println("Hi: " + mName + " " + content);
  9. }
  10. }

Client

  1. public class Client {
  2. public static void main(String[] args) {
  3. Subject infoQ = new Subject();
  4. Coder coder1 = new Coder("linda");
  5. Coder coder2 = new Coder("mary");
  6. Coder coder3 = new Coder("andy");
  7. infoQ.registerObservers(coder1);
  8. infoQ.registerObservers(coder2);
  9. infoQ.registerObservers(coder3);
  10. infoQ.notifyObservers("InfoQ发布新内容了,快来看看吧。");
  11. }
  12. }

优点

  • 观察者和被观察者是抽象耦合的,应对业务变化
  • 增强系统灵活性、可扩展性

缺点

  • 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,如果中间有耗时操作,会影响整体效率,所以一般会考虑异步的方式
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃

Android 中的应用

  • ListView Adapter 数据变化通知,notifyDataSetChanged
  • Eventbus 事件总线设计

参考

技术文章:菜鸟教程-设计模式设计模式系列——观察者模式