简单来说,Observer模式让一个对象(观察者,Observer)去监视另一个对象(目标Subject);它使得目标和观察者之间建立一种 "发布订阅"(publish-subscribe )的关系。通过Observer模式,观察者可以向目标登记,表明自己要从目标接收事件。目标需要向观察者通知事件时,只是简单地将事件发给每一个观察者。
例如:
1.有一个基于某种数据模型的电子表格。只要数据模型发生变化,电子表格就需要更新表格单元以及内嵌的图表。这个例子中,目标是数据模型,观察者是表格单元和图表。当观察者接收到数据模型已经变化的通知时,它们就更新自己。
2.有一个小孩子在睡觉,当这个小孩子醒来的时候,他的父亲,母亲,爷爷,奶奶都要做出一系列的反应。在这个例子中,目标是这个小孩子,观察者是这些父亲,母亲,爷爷,奶奶作出的反应。当小孩子醒过来时,他们各自做出自己的反应。
3.Java的awt中,也使用了Observer模式。例如一个点击一下Button时,可以做出一些反应,可以使弹出一个对话框,关闭界面,打印出信息...
这个例子中,目标就是这个Button,观察者就是作出反应的这些事件。
Observer模式的好处是:它解除了观察者和目标之间的耦合关系。目标不需要知道它的观察者的任何信息。相反,目标只是允许观察者订阅事件。当目标产生一个事件时,它简单地将事件传给每一个观察者。
下面列出了两个小例子:
例一: 模拟awt中点击Button,监视它的事件作出反应。
package edu.smc.dp.observer.awt;
import java.util.ArrayList;
import java.util.List;
public class TestPressButton {
public static void main(String[] args) {
Button button=new Button(); //new 一个Button
button.addActionListener(new MyButtonListener1()); //为Button添加监听时间
button.addActionListener(new MyButtonListener2());
button.pressButton(); //调用点击Button的方法
}
}
class Button{
List<ActionListener> actionListeners=new ArrayList<ActionListener>();
public void pressButton(){
ActionEvent e=new ActionEvent(System.currentTimeMillis(),this);
for(ActionListener actionListener:actionListeners){
actionListener.actionPerform(e);
}
}
public void addActionListener(ActionListener e){
actionListeners.add(e);
}
}
interface ActionListener{
public void actionPerform(ActionEvent e);
}
class ActionEvent{
private long when;
private Object source;
public ActionEvent(long when,Object source){
this.when=when;
this.source=source;
}
public long getWhen() {
return when;
}
public Object getSource() {
return source;
}
}
class MyButtonListener1 implements ActionListener{
@Override
public void actionPerform(ActionEvent e) {
System.out.println("press button 1");
}
}
class MyButtonListener2 implements ActionListener{
@Override
public void actionPerform(ActionEvent e) {
System.out.println("press button 2");
}
}
例二: 当一个小孩子醒过来的时候,他的爷爷,父亲作出反应。
本例用了属性文件,将要作出反应的事件写在属性文件里,然后去读取,在执行。
1.建立属性文件 observers.properties,写入如下内容:
observers=edu.smc.dp.observer.Dad,edu.smc.dp.observer.GrandFather
2.源代码
package edu.smc.dp.observer;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import edu.smc.dp.observer.Test.WakenListener;
class WakeUpEvent{
private long time;
private String loc;
private Object Child;
public WakeUpEvent(long time, String loc, Object child) {
this.time = time;
this.loc = loc;
Child = child;
}
public long getTime() {
return time;
}
public void setTime(long time) {
this.time = time;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public Object getChild() {
return Child;
}
public void setChild(Object child) {
Child = child;
}
}
class Child implements Runnable{
private List<WakenListener> wakenListeners=new ArrayList<WakenListener>();
public Child(){
}
void addWakenUpListener(WakenListener wakenListener){
wakenListeners.add(wakenListener);
}
void wakeUp(){
for(int i=0;i<wakenListeners.size();i++){
WakenListener wakenListener=wakenListeners.get(i);
wakenListener.actionToWakeUp(new WakeUpEvent(System.currentTimeMillis(), "bed", this));
}
}
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.wakeUp();
}
}
class Dad implements WakenListener{
@Override
public void actionToWakeUp(WakeUpEvent wakeUpEvent) {
System.out.println("fead children!");
}
}
class Dog implements WakenListener{
@Override
public void actionToWakeUp(WakeUpEvent arg0) {
System.out.println("wang wang..");
}
}
class GrandFather implements WakenListener{
@Override
public void actionToWakeUp(WakeUpEvent wakeUpEvent) {
// TODO Auto-generated method stub
System.out.println("go to play!");
}
}
public class Test {
interface WakenListener{
void actionToWakeUp(WakeUpEvent wakeUpEvent);
}
public static void main(String[] args) {
Child child=new Child();
try {
String observerStr=PropertyMgr.getProperty("observers");
String[] observers=observerStr.split(",");
for(String observer:observers){
WakenListener wl=(WakenListener) Class.forName(observer).newInstance();
child.addWakenUpListener(wl);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(child).start();
}
}
class PropertyMgr{
private static Properties pros=new Properties();
static{
try {
pros.load(Test.class.getClassLoader().getResourceAsStream("edu/smc/dp/observer/observers.properties"));
String observerStr=pros.getProperty("observers");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getProperty(String key){
return pros.getProperty(key);
}
}