Observer模式也叫觀察者模式,是由GoF提出的23種軟件設計模式的一種。Observer模式是行爲模式之一,它的作用是當一個對象的狀態發生變化時,能夠自動通知其他關聯對象,自動刷新對象狀態
應用場景
- 偵聽事件驅動程序中的外部事件
- 偵聽/監視某個對象的狀態變化
- 發佈者/訂閱者(publisher/subscriber)模型中,當一個外部事件(新的產品, 消息的出現等等)被觸發時,通知郵件列表中的訂閱者
結構模型
JDK對觀察者模式的實現.Observer觀察者與Observable被觀察者
public class Client {
public static void main(String[] args) {
NewsPublisher publisher = new NewsPublisher();
//添加觀察者對象
publisher.addObserver(new SubscriberObserver());
publisher.addObserver(new ManagerObserver());
//發佈新聞,觸發通知事件
publisher.publishNews("Hello news", "news body");
}
}
//被觀察者
class NewsPublisher extends Observable {
public void publishNews(String newsTitle, String newsBody) {
News news = new News(newsTitle, newsBody);
setChanged();//標明對象的狀態已發生變化
System.out.println("News published:" + newsTitle);
this.notifyObservers(news);//通知各Observer,併發送一個名爲news對象的消息
//other process ... such as save news to database
}
}
//觀察者
class SubscriberObserver implements Observer {
public void update(Observable observee, Object param) {
if (param instanceof News) {
mail2Subscriber((News)param);
}
}
private void mail2Subscriber(News news) {
System.out.println("Mail to subscriber. A news published with title:" + news.getTitle());
}
}
//觀察者
class ManagerObserver implements Observer {
public void update(Observable observee, Object param) {
if (param instanceof News) {
mail2Manager((News)param);
}
}
private void mail2Manager(News news) {
System.out.println("Mail to Manager. A news published with title:" + news.getTitle());
}
}
一般優先選擇jdk已經提供的方式.當然我們也可以自己實現.在此之前不妨看看jdk 關於observer與observable的代碼實現.
JDK中的Observer接口和Observable類實現
public interface Observer {
//這個方法被每當觀測目標被改變了,讓被觀察者調用
void update(Observable o, Object arg);
}
public class Observable {
private boolean changed = false;
//觀察者的集合
private Vector obs;
/** Construct an Observable with zero Observers. */
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--)
//通知觀察者,調用觀察者的update()方法
((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() {
R eturn changed;
}
//返回觀察者的數量
public synchronized int countObservers() {
Return obs.size();
}
}
總結:觀察者模式實現相對簡單,但是在一些典型應用中卻很實用.複雜環境可以結合其他的模式 來完成整個模塊或者系統的設計.