观察者模式很好理解,简单来说就是:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。

1. 自己手工创建Observer模式

首先,创建观察者接口:

 public interface Observer {
void update();
}

Publisher接口:

 public interface Publisher {
void add(Observer observer); void delete(Observer observer); void notifyObservers(); void operation();
}

基本功能实现(为了线程安全我们可以选择Vector):

 import java.util.ArrayList;
import java.util.List; public abstract class PublisherAdapter implements Publisher {
private List<Observer> observers = new ArrayList<Observer>(); @Override
public void add(Observer observer) {
observers.add(observer);
} @Override
public void delete(Observer observer) {
observers.remove(observer);
} @Override
public void notifyObservers() {
for (Observer observer : observers)
observer.update();
} }

实现类:

 public class PublisherImpl extends PublisherAdapter {

     @Override
public void operation() {
System.out.println("this is operation");
notifyObservers();
} }

测试类:

 public class Main {

     public static void main(String[] args) {
Publisher impl = new PublisherImpl();
impl.add(new Observer() { @Override
public void update() {
System.out.println("observer 1 receive");
}
});
impl.add(new Observer() { @Override
public void update() {
// TODO Auto-generated method stub
System.out.println("observer 2 receive");
}
});
impl.operation();
} }

测试结果:

this is operation
observer 1 receive
observer 2 receive

2. 使用java.util.Observer接口

这个接口只定义了一个方法:update()。当被观察者(observable)对象的状态发生变化时,这个方法就会被调用。通过调用被观察者对象的notifyObservers()方法通知所有的观察对象。

可以定义被观察者:

 import java.util.Observable;

 public class Publisher extends Observable {
public void operation() {
System.out.println("this is operation");
this.setChanged();
this.notifyObservers();
}
}

则测试方法为:

 import java.util.Observable;
import java.util.Observer; public class Main { public static void main(String[] args) {
Publisher publisher = new Publisher();
publisher.addObserver(new Observer() { @Override
public void update(Observable o, Object arg) {
System.out.println("observer 1 receive");
}
});
publisher.addObserver(new Observer() { @Override
public void update(Observable o, Object arg) {
System.out.println("observer 2 receive");
}
});
publisher.operation();
} }

当然,若要获得被观察者的信息,可以将Observable o转换为Publisher类型:

Publisher p = (Publisher)o;

3. 分析Observer与Observable

如前所述,Observer接口只定义了一个方法:update()。当被观察者对象的状态发生变化时,这个方法就会被调用。java.util.Observer接口定义如下:

 package java.util;

 public interface Observer {
void update(Observable o, Object arg);
}

被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象,这些方法中有两个非常重要:一个是setChanged(),被调用之后会设置一个内部标记变量,代表被观察者对象的状态发生了变化;另一个是notifyObservers(),这个方法被调用时,会调用所有登记过的观察者对象的update()方法。

 package java.util;

 public class Observable {
private boolean changed = false;
private Vector 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 (!changed)
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();
}
}

可用如下类图表示(图片来自于网络):

一个Observable类代表一个被观察者对象。一个被观察者对象可以有多个观察者,一个观察者是一个实现Observer接口的对象。在被观察者对象发生变化时,它会调用notifyObservers方法,此方法再调用所有观察者的update()方法。

同时,发通知的顺序在这里并没有指明。Observerable类所提供的缺省实现会按照Observers对象被登记的次序通知它们(遍历Vector),当然,我们可以在子类中改变这一次序。子类还可以在单独的线程里通知观察者对象、或者在一个公用的线程里按照次序执行。

当一个可观察者对象刚刚创立时,它的观察者集合是空的。两个观察者对象在它们的equals()方法返回true时,被认为是两个相等的对象。

4. 观察者模式总结

来自于:http://www.cnblogs.com/forlina/archive/2011/06/23/2088121.html

优点:

  第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者,它只知道它们都有一个共同的接口。 由于被观察者和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
  第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知

缺点:
  第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察者模式是要特别注意这一点。
  第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
  第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。

观察者模式-Observer的更多相关文章

  1. 设计模式 - 观察者模式(Observer Pattern) 详细说明

    观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  2. 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)

    设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...

  3. 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)

    原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...

  4. 设计模式 - 观察者模式(Observer Pattern) 详细解释

    观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...

  5. java设计模式--观察者模式(Observer)

    java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...

  6. 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)

    观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...

  7. 8.5 GOF设计模式四: 观察者模式Observer

    GOF设计模式四: 观察者模式Observer  现实中遇到的问题  当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式  观察者模式 ...

  8. 设计模式-观察者模式(Observer Pattern)

    观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...

  9. jQuery中的观察者模式(Observer Pattern)

    在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...

  10. [Android&amp;Java]浅谈设计模式-代码篇:观察者模式Observer

    观察者,就如同一个人,对非常多东西都感兴趣,就好像音乐.电子产品.Game.股票等,这些东西的变化都能引起爱好者们的注意并时刻关注他们.在代码中.我们也有这种一种方式来设计一些好玩的思想来.今天就写个 ...

随机推荐

  1. Uva_11916 Emoogle Grid

    题目链接 题意: 有个N X M的棋盘, 有K种颜色, 有B个不可涂色的位置, 共有R种涂色方案. 1)每个可涂色的位置必须涂上一种颜色 2)不可涂色位置不能涂色 3)每个位置必须从K种颜色中选出一种 ...

  2. spm使用之二兼谈spm的贱格

    上一篇还没写完, 因为我觉得太长了, 影响阅读, 就截断继续写. 因为还没有写到修改 创建模块的模板啊. 之所以想到要修改spm用来创建模块的模板, 是因为, 有一天我突然上不了网了, 发现spm完全 ...

  3. [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】

    题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...

  4. importExcel运用注解实现EXCEL导入poi类

    JAVA报表 package com.app.common.excel; import java.io.File; import java.io.FileInputStream; import jav ...

  5. PhoneGap + Dreamweaver 5.5 无法在模拟器中打开的问题(二)

    转载:http://blog.csdn.net/dupang/article/details/8248335 按照网上的教程搭建Dreamweaver CS5.5+PhoneGap移动开发环境,在进行 ...

  6. 【Java】java基本知识

    1.int与Integer的区别 int是基本数据类型,Integer是一个引用数据类型. e.g: int num = 100; // 不是对象 Integer i = 100; // 是对象 // ...

  7. 安卓天天练练(十一)用list绑数据

    之前在练练ListView的时候就有个 BaseAdapter ba = new BaseAdapter() { 用Adapter来绑数据的方法,该方法中 LinearLayout ll=new Li ...

  8. hdu 5067 Harry And Dig Machine

    http://acm.hdu.edu.cn/showproblem.php?pid=5067 思路:问题可以转化成:从某一点出发,遍历网格上的一些点,每个点至少访问一次需要的最小时间是多少.这就是经典 ...

  9. Error creating bean with name 'bookDao'

    “Error creating bean with name 'bookDao' defined in ServletContext resource [/WEB-INF/applicationCon ...

  10. vaddin使用技巧

    添加外部jar包的方法: 在项目目录下建立lib文件夹,把外部jar包复制到该文件夹底下.右键该jar包-构建路径-添加至构建路径即可.也可以配置构建路径-库-添加jar.