觀察者(Observer)模式,又叫 發(fā)布-訂閱(Publish/Subscribe)模式镣陕,模型-視圖(Model-View)模式
定義了一種一對多的依賴關(guān)系谴餐,當主題對象發(fā)生改變的時候會通知所有的觀察者對象。
一個變化其他的相應變化
設計目標:低耦合 + 行動的協(xié)調(diào)一致
上類圖:
觀察者模式.png
java類庫對該模式的支持:
java JDK中定義了Observer
接口呆抑,以及 Observable
的主題角色
AWT1.1+岂嗓,Servlet的委派事件模型(DEM Delegation Event Model)
優(yōu)缺點:
優(yōu)點:觀察者和被觀察者建立了一個抽象的耦合
缺點:
- 如果觀察者比較多,全部通知一下比較耗時
- 如果被觀察者之間有循環(huán)依賴會導致系統(tǒng)崩潰
-
代碼示例:
- 定義個抽象觀察者對象鹊碍,可以直接用JDK自帶的
Observer
接口
package com.byedbl.observer;
/**
* Observer interface
*/
public interface Observer {
public void update(Subject s);
}
- 實現(xiàn)兩個觀察者
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);
}
- 實現(xiàn)抽象主題角色
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;
}
}