[size=large]1、意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
2、别名
依赖(Dependents),发布—订阅(Publish-Subscribe)
3、动机
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相互对象间的一致性。我们不希望为了维护一致性而使各类紧密耦合,因为这样降低了它们的可重用性。
例如,许多图形用户界面工具箱将用户应用的界面表示与底下的应用数据分离。定义应用数据的类和负责界面表示的类可以各自独立地复用。当然它们也可一起工作。一个表格对象和一个柱形对象可使用不同的表示形式描述同一个应用数据对象的信息。表格对象和柱形图形对象互相并不知道对方的存在,这样使你可以根据需要单独复用表格或柱形图。但在这里时它们表现的似乎互相知道,当用户改变表格中的额信息时,柱状图能立即反应这一变化,反过来也是如此。
这一行为意味着表格对象和棒状图对象都依赖于数据对象,因此数据对象的任何状态改变都应立即通知它们。同时也没有理由将依赖于该数据对象的数目限定两个,对相同的数据可以有任意数目的不同用户界面。
Observer模式描述了如何建立这种关系。这一模式中的关键对象是目标(subject)和观察者(observer)。一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。
这种交互也称为发布—订阅(publish-subscribe)。目标是通知的发布者。它发出通知时并不需要知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。
4、适用性
在以下任意情况下可以使用观察者模式:
当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这两者独立封装在独立的对象中以使它们可以各自独立地改变和复用。
当一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
5、结构
[img]http://dl2.iteye.com/upload/attachment/0085/7083/a9e583ab-c6e8-34f3-9cfc-9693b48346d1.jpg[/img]
6、参与者
Subject(目标)
——目标知道它的观察者。可以有任意多个观察者观察同一个目标。
——提供注册和删除观察者对象的接口
Observer(观察者)
——为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject(具体目标)
——将有关状态存入各ConcreteObserver对象。
——当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver(具体观察者)
——维护一个指向ConcreteSubject对象的引用。
——存储有关状态,这些状态应与目标的状态保持一致。
——实现Observer的更新接口以使自身状态与目标的状态保持一致。
7、代码示例
Below is an example written in Java that takes keyboard input and treats each input line as an event. The example is built upon the library classes java.util.Observer and java.util.Observable. When a string is supplied from System.in, the method notifyObservers is then called, in order to notify all observers of the event's occurrence, in the form of an invocation of their 'update' methods - in our example, ResponseHandler.update(...).
The file MyApp.java contains a main() method that might be used in order to run the code.
[/size]
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
2、别名
依赖(Dependents),发布—订阅(Publish-Subscribe)
3、动机
将一个系统分割成一系列相互协作的类有一个常见的副作用:需要维护相互对象间的一致性。我们不希望为了维护一致性而使各类紧密耦合,因为这样降低了它们的可重用性。
例如,许多图形用户界面工具箱将用户应用的界面表示与底下的应用数据分离。定义应用数据的类和负责界面表示的类可以各自独立地复用。当然它们也可一起工作。一个表格对象和一个柱形对象可使用不同的表示形式描述同一个应用数据对象的信息。表格对象和柱形图形对象互相并不知道对方的存在,这样使你可以根据需要单独复用表格或柱形图。但在这里时它们表现的似乎互相知道,当用户改变表格中的额信息时,柱状图能立即反应这一变化,反过来也是如此。
这一行为意味着表格对象和棒状图对象都依赖于数据对象,因此数据对象的任何状态改变都应立即通知它们。同时也没有理由将依赖于该数据对象的数目限定两个,对相同的数据可以有任意数目的不同用户界面。
Observer模式描述了如何建立这种关系。这一模式中的关键对象是目标(subject)和观察者(observer)。一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。
这种交互也称为发布—订阅(publish-subscribe)。目标是通知的发布者。它发出通知时并不需要知道谁是它的观察者。可以有任意数目的观察者订阅并接收通知。
4、适用性
在以下任意情况下可以使用观察者模式:
当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这两者独立封装在独立的对象中以使它们可以各自独立地改变和复用。
当一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
5、结构
[img]http://dl2.iteye.com/upload/attachment/0085/7083/a9e583ab-c6e8-34f3-9cfc-9693b48346d1.jpg[/img]
6、参与者
Subject(目标)
——目标知道它的观察者。可以有任意多个观察者观察同一个目标。
——提供注册和删除观察者对象的接口
Observer(观察者)
——为那些在目标发生改变时需获得通知的对象定义一个更新接口。
ConcreteSubject(具体目标)
——将有关状态存入各ConcreteObserver对象。
——当它的状态发生改变时,向它的各个观察者发出通知。
ConcreteObserver(具体观察者)
——维护一个指向ConcreteSubject对象的引用。
——存储有关状态,这些状态应与目标的状态保持一致。
——实现Observer的更新接口以使自身状态与目标的状态保持一致。
7、代码示例
Below is an example written in Java that takes keyboard input and treats each input line as an event. The example is built upon the library classes java.util.Observer and java.util.Observable. When a string is supplied from System.in, the method notifyObservers is then called, in order to notify all observers of the event's occurrence, in the form of an invocation of their 'update' methods - in our example, ResponseHandler.update(...).
The file MyApp.java contains a main() method that might be used in order to run the code.
[/size]
/* File Name : EventSource.java */
package org.wikipedia.obs;
import java.util.Observable; //Observable is here
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class EventSource extends Observable implements Runnable {
@Override
public void run() {
try {
final InputStreamReader isr = new InputStreamReader(System.in);
final BufferedReader br = new BufferedReader(isr);
while (true) {
String response = br.readLine();
setChanged();
notifyObservers(response);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
/* File Name: ResponseHandler.java */
package org.wikipedia.obs;
import java.util.Observable;
import java.util.Observer; /* this is Event Handler */
public class ResponseHandler implements Observer {
private String resp;
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
resp = (String) arg;
System.out.println("\nReceived Response: " + resp );
}
}
}
/* Filename : MyApp.java */
/* This is the main program */
package org.wikipedia.obs;
public class MyApp {
public static void main(String[] args) {
System.out.println("Enter Text >");
// create an event source - reads from stdin
final EventSource eventSource = new EventSource();
// create an observer
final ResponseHandler responseHandler = new ResponseHandler();
// subscribe the observer to the event source
eventSource.addObserver(responseHandler);
// starts the event thread
Thread thread = new Thread(eventSource);
thread.start();
}
}