先看看壹個生活中的例子:
我們使用想瀏覽Java相關的文章,於是我們點擊訂閱了[Java專題],當[Java專題]有新文章發布就會推送給我們,當然其他人也可以訂閱[Java專題]並收到[Java專題]的推送。這就是觀察者。 定義對象間的壹對多關系,當壹個對象的狀態發生變化時,所依賴於它的對象都得到通知並主動更新。在觀察者模式中,多個訂閱者成為觀察者(Observer),被觀察的對象成為目標(Subject)。
實現觀察者模式的方法不只壹種,但是以包含Subject與Observer接口的類設計的做法最常見。(Java API 內置觀察者模式用的是Observer接口與Observable類)
觀察者模式UML圖:
先定義觀察者模式的接口
在觀察者模式的實現上,有推模式和拉模式兩種方式。
上面例子中
void updateByPush(Object obj) 就是推模式;
void updateByPull(Subject subject)就是拉模式
java.util包內包含最基本的Observer接口與Observable類(其實對應的就是Subject類)
我們看壹下Observer源碼
我們看到update更新方法有兩個參數:Observable、Object,可見Java API 內置觀察者模式同時支持[拉]和[取]
我們再來看看Observable類源碼
註意Observable是壹個類,而不是接口,這有壹定的局限性。因為如果某個類想同時具有Observable類和另壹個超類的行為,就會陷入兩難,畢竟Java不支持多重繼承。
有點需要特別提壹下的就是,Java API 內置的Observable需要調用壹下 setChanged();觀察者才能收到推送,我們看壹下源碼,發現notifyObservers方法裏有判斷changed的狀態為true才去通知觀察者。
我們自己實現觀察者模式的時候是沒有這壹點的,那加上這壹個標誌位有什麽好處?好處就是更靈活,Observable類只提供這個boolean值來表明是否發生變化,而不定義什麽叫變化,因為每個業務中對變化的具體定義不壹樣,因此子類自己來判斷是否變化;該變量既提供了壹種抽象(變與不變),同時提供了壹種觀察者更新狀態的可延遲加載,通過後面的notifyObservers方法分析可知觀察者是否會調用update方法,依賴於changed變量,因此即使被觀察者在邏輯上發生改變了,只要不調用setChanged,update是不會被調用的。如果我們在某些業務場景不需要頻繁觸發update,則可以適時調用setChanged方法來延遲刷新。
阿裏雲折扣快速入口