观察者(Observer)模式,又叫 发布-订阅(Publish/Subscribe)模式,模型-视图(Model-View)模式
定义了一种一对多的依赖关系,当主题对象发生改变的时候会通知所有的观察者对象。
一个变化其他的相应变化
设计目标:低耦合 + 行动的协调一致
上类图:
java类库对该模式的支持:
java JDK中定义了Observer
接口,以及 Observable
的主题角色
AWT1.1+,Servlet的委派事件模型(DEM Delegation Event Model)
优缺点:
优点:观察者和被观察者建立了一个抽象的耦合
缺点:
- 如果观察者比较多,全部通知一下比较耗时
- 如果被观察者之间有循环依赖会导致系统崩溃
-
代码示例:
- 定义个抽象观察者对象,可以直接用JDK自带的
Observer
接口
package com.byedbl.observer;
/**
* Observer interface
*/
public interface Observer {
public void update(Subject s);
}
- 实现两个观察者
package com.byedbl.observer;
/**
* A concrete observer
* This concrete observer can change subject through call
* a concrete subject setState function
*/
import java.util.Vector;
public class ObserverA implements Observer {
private Vector strVector;
private Subject sub;
public ObserverA(Subject s) {
sub = s;
//strVector = new Vector();
}
public void update(Subject subject) {
strVector = subject.getState();
System.out.println("----- ObserverA will be updated -----");
for(int i = 0; i < strVector.size(); i++) {
System.out.println("Num " + i + " is :" + (String)strVector.get(i));
}
}
public void change(String action, String str) {
sub.setState(action, str);
//we can auto update
//sub.sendNotify();
}
public void notifySub() {
sub.sendNotify();
}
}
package com.byedbl.observer; /**
* A concrete observer
* This observer, can not change subject,
* but it can print the content in vector sorted by alphameric
*/
import java.util.Vector;
public class ObserverB implements Observer {
private Vector strVector;
public ObserverB() {
strVector = new Vector();
}
public void update(Subject subject) {
strVector = (Vector)(subject.getState()).clone();
//----- Sorted vector ---------------------------
for (int i = strVector.size(); --i >= 0; ) {
for (int j = 0; j < i; j++) {
String str1 = (String)strVector.get(j);
String str2 = (String)strVector.get(j+1);
if((str1.compareTo(str2)) > 0) {
strVector.setElementAt(str2, j);
strVector.setElementAt(str1, j+1);
}
}
}
System.out.println("----- ObserverB will be updated -----");
for(int i = 0; i < strVector.size(); i++) {
System.out.println("Num " + i + " is :" + (String)strVector.get(i));
}
}
}
- 定义抽象主题角色
package com.byedbl.observer; /**
* Subject interface
* In this interface , we can only declare top 3 function,
* other function we can define in an abstract class which implements
* this interface
*/
import java.util.*;
public interface Subject {
public abstract void attach(Observer o);
public abstract void detach(Observer o);
public abstract void sendNotify();
public abstract Vector getState();
public abstract void setState(String act, String str);
}
- 实现抽象主题角色
package com.byedbl.observer;
/**
* A concrete subject
*/
import java.util.LinkedList;
import java.util.Vector;
public class ConcreteSubject implements Subject {
private LinkedList observerList;
private Vector strVector;
public ConcreteSubject() {
observerList = new LinkedList();
strVector = new Vector();
}
public void attach(Observer o) {
observerList.add(o);
}
public void detach(Observer o) {
observerList.remove(o);
}
public void sendNotify() {
for (int i = 0; i < observerList.size(); i++) {
((Observer) observerList.get(i)).update(this);
}
}
public void setState(String act, String str) {
if (act.equals("ADD")) {
strVector.add(str);
} else if (act.equals("DEL")) {
strVector.remove(str);
}
}
public Vector getState() {
return strVector;
}
}
- 客户端代码
package com.byedbl.observer;
/**
* A concrete subject
*/
import java.util.LinkedList;
import java.util.Vector;
public class ConcreteSubject implements Subject {
private LinkedList observerList;
private Vector strVector;
public ConcreteSubject() {
observerList = new LinkedList();
strVector = new Vector();
}
public void attach(Observer o) {
observerList.add(o);
}
public void detach(Observer o) {
observerList.remove(o);
}
public void sendNotify() {
for (int i = 0; i < observerList.size(); i++) {
((Observer) observerList.get(i)).update(this);
}
}
public void setState(String act, String str) {
if (act.equals("ADD")) {
strVector.add(str);
} else if (act.equals("DEL")) {
strVector.remove(str);
}
}
public Vector getState() {
return strVector;
}
}