观察者模式-Observer
观察者模式很好理解,简单来说就是:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。
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的更多相关文章
- 设计模式 - 观察者模式(Observer Pattern) 详细说明
观察者模式(Observer Pattern) 详细说明 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- 设计模式 ( 十六 ) 观察者模式Observer(对象行为型)
设计模式 ( 十六 ) 观察者模式Observer(对象行为型) 1.概述 一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力.当对象们连接在一起时,它们就可以相互提供服务和信息. 通常来 ...
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式 - 观察者模式(Observer Pattern) 详细解释
观察者模式(Observer Pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26583157 版权全部 ...
- java设计模式--观察者模式(Observer)
java设计模式--观察者模式(Observer) java设计模式--观察者模式(Observer) 观察者模式的定义: 定义对象间的一种一对多的依赖关系.当一个对象的状态发生改变时,所有依赖于它的 ...
- 观察者模式 Observer 发布订阅模式 源 监听 行为型 设计模式(二十三)
观察者模式 Observer 意图 定义对象一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖他的对象都得到通知并自动更新. 别名:依赖(Dependents),发布订阅(Publish-Su ...
- 8.5 GOF设计模式四: 观察者模式Observer
GOF设计模式四: 观察者模式Observer 现实中遇到的问题 当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式 观察者模式 ...
- 设计模式-观察者模式(Observer Pattern)
观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己. 观察者 ...
- jQuery中的观察者模式(Observer Pattern)
在jQuery中,on方法可以为元素绑定事件,trigger方法可以手动触发事件,围绕这2个方法,我们来体验jQuery中的观察者模式(Observer Pattern). ■ on方法绑定内置事件, ...
- [Android&Java]浅谈设计模式-代码篇:观察者模式Observer
观察者,就如同一个人,对非常多东西都感兴趣,就好像音乐.电子产品.Game.股票等,这些东西的变化都能引起爱好者们的注意并时刻关注他们.在代码中.我们也有这种一种方式来设计一些好玩的思想来.今天就写个 ...
随机推荐
- js共享onload事件
问题:通过js进行事件绑定,必须在HTML文档加载完成后再执行js脚本,否则可能因DOM不完整导致无法完成预计的效果,但对于不同的需求如何选用最佳的实现方式呢,这里做了整理,可以做参考. 一.对于小型 ...
- Test for open live write
this is test document. this is test document. this is test document. this is test document. this is ...
- Coursera《machine learning》--(2)单变量线性回归(Linear Regression with One Variable)
本笔记为Coursera在线课程<Machine Learning>中的单变量线性回归章节的笔记. 2.1 模型表示 参考视频: 2 - 1 - Model Representation ...
- Contest20140705 testB DP
testB 输入文件: testB.in 输出文件testB.out 时限2000ms 问题描述: 方师傅有两个由数字组成的串 a1,a2,⋯,an 和 b1,b2,⋯,bm.有一天,方师傅感到十分无 ...
- BZOJ 3994 约数个数和
Description 设\(d(x)\)为\(x\)的约数个数,给定\(N,M\),求\[\sum_{i=1}^{N}\sum_{j=1}^{M}d(ij)\]. Input 输入文件包含多组测试数 ...
- BZOJ 3569 DZY Loves Chinese II
Description 神校XJ之学霸兮,Dzy皇考曰JC. 摄提贞于孟陬兮,惟庚寅Dzy以降. 纷Dzy既有此内美兮,又重之以修能. 遂降临于OI界,欲以神力而凌♂辱众生. 今Dzy有一魞歄图,其上 ...
- iOS:关于获取网络类型和运营商信息
目录 1. 获取运营商网络类型 2. 获取运营商信息 返回目录 1. 获取运营商网络类型 Apple的Reachability Sample看起来不错,但是只可以判断是否连接到互联网和是否连接Wifi ...
- Spring MVC 中的REST支持
本部分提供了支持 RESTful web 服务的主要 Spring 功能(或注释)的概述. @Controller 使用 @Controller 注释对将成为 MVC 中控制器的类进行注释并处理 HT ...
- Android 中LocalBroadcastManager的使用方式
Android 中LocalBroadcastManager的使用方式 在android-support-v4.jar中引入了LocalBroadcastManager,称为局部通知管理器,这种通知的 ...
- 【HDOJ】1606 Excuses, Excuses!
简单字符串. #include <cstdio> #include <cstring> #define MAXLEN 105 #define MAXN 25 char keys ...