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

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. iOS中默认样式修改-b

    项目中有大量的UITableView都需要显示sectionHeader.iOS中默认sessionHeader上的textLabel样式跟设计图不符. 按照我们之前的解决方案,是在每个UITable ...

  2. window—BAT脚本

    bat脚本注释方法: 1.:: 注释内容(第一个冒号后也可以跟任何一个非字母数字的字符) 2.rem 注释内容(不能出现重定向符号和管道符号) 3.echo 注释内容(不能出现重定向符号和管道符号)〉 ...

  3. Hadoop 学习笔记 (十) MapReduce实现排序 全局变量

    一些疑问:1 全排序的话,最后的应该sortJob.setNumReduceTasks(1);2 如果多个reduce task都去修改 一个静态的 IntWritable ,IntWritable会 ...

  4. POOL

    #ifndef POOL_HHH #define POOL_HHH #include "common.h" /* simple and fast obj pool without ...

  5. 使用maven profile实现多环境可移植构建

    mvn clean package -Pproduction即构建出生产环境需要的war包 mvn tomcat:redeploy -Ptest 即发布到测试环境 在开发过程中,我们的软件会面对不同的 ...

  6. tomcat 系统架构与设计模式 第二部分 设计模式 转

    Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析 许 令波, Java 开发工程师, 淘宝网 许令波,现就职于淘宝网,是一名 Java 开发工程师.对大型互联网架构设计颇感兴趣,并对一些 ...

  7. 服务器RAID配置全程与RAID基础知识

    服务器RAID配置全程 一.RAID介绍 RAID是Redundent Array of Inexpensive Disks的缩写,直译为“廉价冗余磁盘阵列”,也简称为“磁盘阵列”.后来RAID中的字 ...

  8. WindowsPhone 8 开发 之 本地数据库应用

    微软提供的有一个本地数据库的例子 http://code.msdn.microsoft.com/wpapps/Local-Database-Sample-57b1614c 可以进行参照. 里边最核心的 ...

  9. C#调用C++动态库(dll)

    在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用re ...

  10. Xamarin最新crack 包含IOS

    Xamarin.Android 4.10.01068 & Xamarin.iOS 1.8.361 28 Comments   tweet     inShare   NEW support f ...