http://blog.csdn.net/tianjf0514/article/details/7475164/

一、观察者模式介绍

在Java中通过Observable类和Observer接口实现了观察者模式。一个Observer对象监视着一个Observable对象的变化,当Observable对象发生变化时,Observer得到通知,就可以进行相应的工作。

如果画面A是显示数据库里面的数据,而画面B修改了数据库里面的数据,那么这时候画面A就要重新Load。这时候就可以用到观察者模式

二、观察者模式实现方法

java.util.Observable中有两个方法对Observer特别重要

①setChanged()方法

  1. /**
  2. * Sets the changed flag for this {@code Observable}. After calling
  3. * {@code setChanged()}, {@code hasChanged()} will return {@code true}.
  4. */
  5. protected void setChanged() {
  6. changed = true;
  7. }

②notifyObservers()方法 / notifyObservers(Object data)方法

  1. /**
  2. * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
  3. * method for every observer in the list of observers using null as the
  4. * argument. Afterwards, calls {@code clearChanged()}.
  5. * <p>
  6. * Equivalent to calling {@code notifyObservers(null)}.
  7. */
  8. public void notifyObservers() {
  9. notifyObservers(null);
  10. }
  11. /**
  12. * If {@code hasChanged()} returns {@code true}, calls the {@code update()}
  13. * method for every Observer in the list of observers using the specified
  14. * argument. Afterwards calls {@code clearChanged()}.
  15. *
  16. * @param data
  17. *            the argument passed to {@code update()}.
  18. */
  19. @SuppressWarnings("unchecked")
  20. public void notifyObservers(Object data) {
  21. int size = 0;
  22. Observer[] arrays = null;
  23. synchronized (this) {
  24. if (hasChanged()) {
  25. clearChanged();
  26. size = observers.size();
  27. arrays = new Observer[size];
  28. observers.toArray(arrays);
  29. }
  30. }
  31. if (arrays != null) {
  32. for (Observer observer : arrays) {
  33. observer.update(this, data);
  34. }
  35. }
  36. }

以上两个方法十分重要

setChanged()方法 ——

用来设置一个内部标志位注明数据发生了变化

notifyObservers()方法 / notifyObservers(Object data)方法 ——

通知所有的Observer数据发生了变化,这时所有的Observer会自动调用复写好的update(Observable observable, Object data)方法来做一些处理(比如说画面数据的更新)。

我们可以看到通知Observer有两个方法,一个无参,一个有参。那么这个参数有什么作用呢?

其中一个作用:现在我不想通知所有的Observer,而只想其中一个指定的Observer做一些处理,那么就可以传一个参数作为ID,然后在所有的Observer中判断,每个Observer判断只有接收到底参数ID是属于自己的才做一些处理。

当然参数还有其他作用,我只是举了个例子。

下面举个例子加以说明:

  1. import java.util.Observable;
  2. /**
  3. * 被观察者类
  4. */
  5. public class SimpleObservable extends Observable
  6. {
  7. private int data = 0;
  8. public int getData(){
  9. return data;
  10. }
  11. public void setData(int i){
  12. if(this.data != i) {
  13. this.data = i;
  14. setChanged();
  15. //只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。
  16. notifyObservers();
  17. }
  18. }
  19. }

上面这个类是一个被观察者类,它继承了Observable类,表示这个类是可以被观察的。

然后在setData()方法里面,也就是数据改变的地方,来调用Observable类的setChanged()方法和notifyObservers()方法,表示数据已改变并通知所有的Observer调用它们的update()方法做一些处理。

注意:只有在setChange()被调用后,notifyObservers()才会去调用update(),否则什么都不干。

  1. /**
  2. * 观察者类
  3. */
  4. public class SimpleObserver implements Observer
  5. {
  6. public SimpleObserver(SimpleObservable simpleObservable){
  7. simpleObservable.addObserver(this );
  8. }
  9. public void update(Observable observable ,Object data){  // data为任意对象,用于传递参数
  10. System.out.println(“Data has changed to” + (SimpleObservable)observable.getData());
  11. }
  12. }

通过生成被观察者(SimpleObservable类)的实例,来调用addObserver(this)方法让观察者(SimpleObserver类)达到观察被观察者(SimpleObservable类)的目的。

然后还要复写update()方法,做数据改变后的一些处理。

下面可以写一个简单的测试类来测试一下

  1. public class SimpleTest
  2. {
  3. public static void main(String[] args){
  4. SimpleObservable doc = new SimpleObservable ();
  5. SimpleObserver view = new SimpleObserver (doc);
  6. doc.setData(1);
  7. doc.setData(2);
  8. doc.setData(2);
  9. doc.setData(3);
  10. }
  11. }

运行结果如下

  1. Data has changed to 1
  2. Data has changed to 2  //第二次setData(2)时由于没有setChange,所以update没被调用
  3. Data has changed to 3

下面介绍一个Observable类的其他一些属性和方法

属性 ——

  1. // observers是一个List,保存着所有要通知的observer。
  2. List<Observer> observers = new ArrayList<Observer>();
  3. // changed是一个boolean型标志位,标志着数据是否改变了。
  4. boolean changed = false;

方法 ——

  1. // 添加一个Observer到列表observers中
  2. public void addObserver(Observer observer) {
  3. if (observer == null) {
  4. throw new NullPointerException();
  5. }
  6. synchronized (this) {
  7. if (!observers.contains(observer))
  8. observers.add(observer);
  9. }
  10. }
  11. // 从列表observers中删除一个observer
  12. public synchronized void deleteObserver(Observer observer) {
  13. observers.remove(observer);
  14. }
  15. // 清空列表observers
  16. public synchronized void deleteObservers() {
  17. observers.clear();
  18. }
  19. // 返回列表observers中observer的个数
  20. public int countObservers() {
  21. return observers.size();
  22. }
  23. // 重置数据改变标志位为未改变
  24. protected void clearChanged() {
  25. changed = false;
  26. }
  27. // 将数据改变标志位设置为改变
  28. protected void setChanged() {
  29. changed = true;
  30. }
  31. // 判断标志位的值
  32. public boolean hasChanged() {
  33. return changed;
  34. }
  35. // 通知所有observer(无参)
  36. public void notifyObservers() {
  37. notifyObservers(null);
  38. }
  39. // 通知所有observer(有参)
  40. @SuppressWarnings("unchecked")
  41. public void notifyObservers(Object data) {
  42. int size = 0;
  43. Observer[] arrays = null;
  44. synchronized (this) {
  45. if (hasChanged()) {
  46. clearChanged();
  47. size = observers.size();
  48. arrays = new Observer[size];
  49. observers.toArray(arrays);
  50. }
  51. }
  52. if (arrays != null) {
  53. for (Observer observer : arrays) {
  54. observer.update(this, data);
  55. }
  56. }
  57. }

注意:在Observer对象销毁前一定要用deleteObserver将其从列表中删除,也就是在onDestroy()方法中调用deleteObserver()方法。

不然因为还存在对象引用的关系,Observer对象不会被垃圾收集,造成内存泄漏,并且已死的Observer仍会被通知到,有可能造成意料外的错误,而且随着列表越来越大,notifyObservers操作也会越来越慢。

下面2个工程是Observable与Observer的经典运用,是Android实现的单指拖动放大图片的操作

两个例子:

http://download.csdn.net/detail/tianjf0514/4237628

http://download.csdn.net/download/tianjf0514/4237634

Java_观察者模式(Observable和Observer)的更多相关文章

  1. java中观察者模式Observable和Observer

    25.java中观察者模式Observable和Observer 如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的 ...

  2. 设计模式之观察者模式(Observable与Observer)

    设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...

  3. 25、java中观察者模式Observable和Observer

    如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的购房者都在关注着房子的价格变化,每当房子价格变化的时候,所有的购房 ...

  4. Java_观察者模式(Observable和Observer) -转

    原文地址: Java_观察者模式(Observable和Observer) 一.观察者模式介绍    在Java中通过Observable类和Observer接口实现了观察者模式.一个Observer ...

  5. 十一、观察者模式(Observable、Observer)

    老板出差了,员工1.员工2..均放羊中.他们请求前台的秘书,当老板回来时通知自己,免得被Boss抓个现行.秘书想了想,说————嗯,这是观察者模式. 当一个对象的改变需要同时改变其它对象,而且它不知道 ...

  6. RxJava 设计理念 观察者模式 Observable lambdas MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. [RxJS] Subject: an Observable and Observer hybrid

    This lesson teaches you how a Subject is simply a hybrid of Observable and Observer which can act as ...

  8. OpenJDK源码研究笔记(六)--观察者模式工具类(Observer和Observable)和应用示例

    本文主要讲解OpenJDK观察者模式的2个工具类,java.util.Observer观察者接口,java.util.Observable被观察者基类. 然后,给出了一个常见的观察者应用示例. Obs ...

  9. Java常用类库--观察者设计模式( Observable类Observer接口)

    如果要想实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口. import java.util.* ; class House extends Obse ...

随机推荐

  1. 09Mybatis_入门程序——删除用户以及更新用户

    删除用户: 还是前面的的案例,别的都不改,就修改两处地方.1.user.xml文件以及2.Mybatis_first.java文件 user.xml文件代码修改如下: <?xml version ...

  2. RDLC系列之四 常见错误

    解决 RDLC 报表自动分页表头显示问题 原文:http://www.th7.cn/Program/net/201207/85445.shtml RDLC是用XML来描述一个报表相关的一切,只需要在& ...

  3. Delphi的基于接口(IInterface)的多播监听器模式(观察者模式 )

    本文来自:http://www.cnblogs.com/hezihang/p/6083555.html Delphi采用接口方式设计模块,可以降低模块之间的耦合,便于扩展和维护.本文提供一个实现基于接 ...

  4. no2.crossdomain.xml批量读取(待完善)

    读取太多url有问题 #coding=utf-8 import urllib import requests import sys import re import time def getxml(u ...

  5. ZooKeeper学习第五期--ZooKeeper管理分布式环境中的数据

    引言 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它涉及到了paxos算法.Zab协议.通信协议等相关知识,理解起来比较抽象所以还需要借助一些应用场景,来帮我们 ...

  6. Asp.net设计模式笔记之一:理解设计模式

    GOF设计模式著作中的23种设计模式可以分成三组:创建型(Creational),结构型(Structural),行为型(Behavioral).下面来做详细的剖析. 创建型 创建型模式处理对象构造和 ...

  7. 利用javascript和WebGL绘制地球 【翻译】

    利用javascript和WebGL绘制地球 [翻译] 原翻译:利用javascript和WebGL绘制地球 [翻译] 在我们所有已知的HTML5API中,WebGL可能是最有意思的一个,利用这个AP ...

  8. HoloLens开发手记 - Unity之Gestures手势识别

    手势识别是HoloLens交互的重要输入方法之一.HoloLens提供了底层API和高层API,可以满足不同的手势定制需求.底层API能够获取手的位置和速度信息,高层API则借助手势识别器来识别预设的 ...

  9. Unity3D独立游戏开发日记(一):动态生成树木

    目前写的独立游戏是一个沙盒类型的游戏.游戏DEMO视频如下: 提到沙盒类型的游戏,就有人给出了这样的定义: 游戏世界离现实世界越近,自由度.随机度越高才叫沙盒游戏.所谓自由度,就是你在游戏里想干啥就干 ...

  10. node 通用的中间件

    为什么学习Node,因为他的门槛比较高一点,现在比较热门一点. 技术这种东西,用最短的时间学会了收益终身. 1.常用的中间件: // 通用的中间件 //bodyParser connect 内建的中间 ...