手记

java设计模式-观察者模式

定义:
使用head First 设计模式中提到的说法

观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监听一个主题对象。这样一来,当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。

简介:

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。

面向对象设计的一个原则是:

系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
实现方式

实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

组成元素:
主题
主题是观察者观察的对象,一个主题必须具备下面三个特征。

持有监听的观察者的引用
支持增加和删除观察者
主题状态改变,通知观察者

观察者

当主题发生变化,收到通知进行具体的处理是观察者必须具备的特征。

1.自定义实现例子:

代码:(使用了泛型和反射)




2.java内置的实现方式:

java.util.Observable 这是一个类,而非接口,主题需要继承这个类。

java.util.Observer 这是一个接口,监听者需要实现这个接口。

代码:
import java.util.Observable;
import java.util.Observer;
public class MainRoot {
  public static void main(String[] args) {
      Observer consumer = new Consumer();
      MilkProvider provider = new MilkProvider();
      provider.addObserver(consumer);
      provider.milkProduced();
  }

  static class MilkProvider extends Observable {
      public void milkProduced() {
          setChanged();//状态改变,必须调用
          notifyObservers();
      }
  }

  static class Consumer implements Observer {
      @Override
      public void update(Observable arg0, Object arg1) {
          System.out.println("Consumer update..." + arg0 + ";arg1=" + arg1);
      }
  }
}
setChange讲解

源代码:

protected synchronized void setChanged() {
    changed = true;
}
setChange的意义:

1.筛选有效通知,只有有效通知可以调用setChanged。比如,我的微信朋友圈一条状态,好友A点赞,后续该状态的点赞和评论并不是每条都通知A,只有A的好友触发的操作才会通知A。

2.便于撤销通知操作,在主题中,我们可以设置很多次setChanged,但是在最后由于某种原因需要取消通知,我们可以使用clearChanged轻松解决问题。

3.主动权控制,由于setChanged为protected,而notifyObservers方法为public,这就导致存在外部随意调用notifyObservers的可能,但是外部无法调用setChanged,因此真正的控制权应该在主题这里。

如何主动获取通知:
需要主题为某些数据提供getter方法,观察者只需调用getter取数据处理即可。
代码:
static class MilkProvider extends Observable {
    public void milkProduced() {
      setChanged();//状态改变,必须调用
      notifyObservers();
    }

    public float getPrice() {
      return 2.5f;
    }
  }

  static class Consumer implements Observer {
    @Override
    public void update(Observable arg0, Object arg1) {
        MilkProvider provider = (MilkProvider)arg0;
        System.out.println("milk price =" + provider.getPrice());
    }
  }
观察者模式的优点:

1.观察者增加或删除无需修改主题的代码,只需调用主题对应的增加或者删除的方法即可。

2.主题只负责通知观察者,但无需了解观察者如何处理通知。

3.观察者只需等待主题通知,无需观察主题相关的细节。

4.由于被动接受,正常情况下不会错过主题的改变通知。而主动获取的话,由于时机选取问题,可能导致错过某些状态。

缺点:

1.主题持有观察者的引用,如果未正常处理从主题中删除观察者,会导致观察者无法被回收。

2.如果观察者具体实现代码有问题,会导致主题和观察者对象形成循环引用,在某些采用引用计数的垃圾回收器可能导致无法回收。

我的微信号:rdst6029930

欢迎交流

参考:

http://baike.baidu.com/view/1854779.htm
http://droidyue.com/blog/2015/06/27/desgign-pattern-observer/index.html

3人推荐
随时随地看视频
慕课网APP