前言
在日常生活中,比如我們訂閱報紙或者訂牛奶。或者在網絡上,RSS方式訂閱別人的博客,微博follow某人,以及現在很火的即刻app。都是采取的訂閱的模式。當我們需要報紙,牛奶,以及查看別人博客/微博,或是某種主題的消息,我們只需采取訂閱的方式在發(fā)布方注冊一下即可。當我們不需要的時候,只要取消訂閱就可以了。在軟件開發(fā)中,同樣有利用這種原理的設計模式——觀察者模式。
是什么
觀察者模式(Observer Pattern):定義對象之間的一種一對多依賴關系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關依賴對象都得到通知并被自動更新。
觀察者模式的別名包括發(fā)布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監(jiān)聽器(Source/Listener)模式或從屬者(Dependents)模式。觀察者模式是一種對象行為型模式。
下圖就是觀察者模式結構圖:
有如下角色:
- Subject: 目標
- ConcreteSubject:具體目標
- Observer: 觀察者
- ConcreteObserver:具體觀察者

為什么
還是以日常生活舉例,當我們想要查看某人的博客是否有更新的時候。我們可以直接在瀏覽器中輸入博客地址進行查看。但是這樣一種方式,往往效率不高。有可能幾天內都沒有更新。但是如果我們采用RSS方式訂閱的話,我們能在第一事件收到對方博客更新的消息。其他時候,我們可以處理別的事物,而不用主動查看是否有更新。同理,在軟件開發(fā)中。一些對象如果對對象A的狀態(tài)的變化感興趣,采用觀察者模式來訂閱它的狀態(tài)更新,這樣就不用持有對象A的引用了。降低了對象之間的耦合。
怎么做
首先是主題Subject類的實現,它使用集合持有訂閱者,訂閱者通過attach方法訂閱主題,detach方法取消訂閱,當主題的state發(fā)生變化時,通過notifyObservers通知訂閱者,主題狀態(tài)有更新:
/**
* 主題,被觀察對象
*/
public class Subject {
private List<Observer> observers = new ArrayList<>();//訂閱者鏈表
private int state;//主題狀態(tài)
public void attach(Observer observer){
if(observer!=null){
observers.add(observer);
}
}
public void detach(Observer observer){
observers.remove(observer);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
notifyObservers();
}
public void notifyObservers(){
for(Observer observer:observers){
observer.update(this);
}
}
}
然后時訂閱者類的實現,一般是一個抽象類或者接口:
/**
* 觀察者
*/
public interface Observer {
void update(Subject subject);
}
接著時具體觀察者類的實現,在update方法中對主題狀態(tài)改變進行具體操作:
public class BinaryObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Binary String:"+Integer.toBinaryString(subject.getState()));
}
}
public class HexObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Hex String:"+Integer.toHexString(subject.getState()));
}
}
public class OctalObserver implements Observer {
@Override
public void update(Subject subject) {
System.out.println("Octal String:"+Integer.toOctalString(subject.getState()));
}
}
最后,我們寫個Client類看看具體應用:
public class Client {
public static void main(String[] args) {
Subject subject = new Subject();
HexObserver hexObserver = new HexObserver();
OctalObserver octalObserver = new OctalObserver();
BinaryObserver binaryObserver = new BinaryObserver();
//觀察者訂閱主題
subject.attach(hexObserver);
subject.attach(octalObserver);
subject.attach(binaryObserver);
System.out.println("Set state:15");
subject.setState(15);//設置狀態(tài)
System.out.println("-----------------");
//取消訂閱主題
subject.detach(octalObserver);
System.out.println("Set state:24");
subject.setState(24);//改變狀態(tài)
}
}
運行結果:
