一、定義
觀察者模式(Observer Pattern)也叫做發(fā)布訂閱模式(Publish/subscribe),它是一個(gè)在項(xiàng) 目中經(jīng)常使用的模式,其定義如下:
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.(定義對(duì)象間一種一對(duì)多的依賴關(guān)系战转,使得每 當(dāng)一個(gè)對(duì)象改變狀態(tài),則所有依賴于它的對(duì)象都會(huì)得到通知并被自動(dòng)更新杉辙。)
觀察者模式的通用類圖挑秉,如圖所示。
我們先來解釋一下觀察者模式的幾個(gè)角色名稱:
- Subject被觀察者
定義被觀察者必須實(shí)現(xiàn)的職責(zé)勋磕,它必須能夠動(dòng)態(tài)地增加妈候、取消觀察者。它一般是抽象類 或者是實(shí)現(xiàn)類挂滓,僅僅完成作為被觀察者必須實(shí)現(xiàn)的職責(zé):管理觀察者并通知觀察者苦银。
- Observer觀察者
觀察者接收到消息后,即進(jìn)行update(更新方法)操作赶站,對(duì)接收到的信息進(jìn)行處理幔虏。
- ConcreteSubject具體的被觀察者
定義被觀察者自己的業(yè)務(wù)邏輯,同時(shí)定義對(duì)哪些事件進(jìn)行通知贝椿。
- ConcreteObserver具體的觀察者
每個(gè)觀察在接收到消息后的處理反應(yīng)是不同想括,各個(gè)觀察者有自己的處理邏輯。
被觀察者
public abstract class Subject {
//定義一個(gè)觀察者數(shù)組
private Vector<Observer> obsVector = new Vector<Observer>();
//增加一個(gè)觀察者
public void addObserver(Observer o){
this.obsVector.add(o);
}
//刪除一個(gè)觀察者
public void delObserver(Observer o){
this.obsVector.remove(o);
}
//通知所有觀察者
public void notifyObservers(){
for(Observer o:this.obsVector){
o.update();
}
}
}
//具體被觀察者
public class ConcreteSubject extends Subject {
//具體的業(yè)務(wù)
public void doSomething(){
/*
* do something
*/
super.notifyObservers();
}
}
//觀察者
public interface Observer {
//更新方法
public void update();
}
//具體觀察者
public class ConcreteObserver implements Observer {
//實(shí)現(xiàn)更新方法
public void update() {
System.out.println("接收到信息团秽,并進(jìn)行處理主胧!");
}
}
//場(chǎng)景類
public class Client {
public static void main(String[] args) {
//創(chuàng)建一個(gè)被觀察者
ConcreteSubject subject = new ConcreteSubject();
//定義一個(gè)觀察者
Observer obs= new ConcreteObserver();
//觀察者觀察被觀察者
subject.addObserver(obs);
//觀察者開始活動(dòng)了
subject.doSomething();
}
}
二、應(yīng)用
2.1 優(yōu)點(diǎn)
- 觀察者和被觀察者之間是抽象耦合
如此設(shè)計(jì)习勤,則不管是增加觀察者還是被觀察者都非常容易擴(kuò)展,而且在Java中都已經(jīng)實(shí) 現(xiàn)的抽象層級(jí)的定義焙格,在系統(tǒng)擴(kuò)展方面更是得心應(yīng)手图毕。
- 建立一套觸發(fā)機(jī)制
根據(jù)單一職責(zé)原則,每個(gè)類的職責(zé)是單一的眷唉,那么怎么把各個(gè)單一的職責(zé)串聯(lián)成真實(shí)世 界的復(fù)雜的邏輯關(guān)系呢予颤?比如,我們?nèi)ゴ颢C冬阳,打死了一只母鹿蛤虐,母鹿有三個(gè)幼崽,因失去了 母鹿而餓死肝陪,尸體又被兩只禿鷹爭(zhēng)搶驳庭,因分配不均,禿鷹開始斗毆,然后羸弱的禿鷹死掉饲常,生存下來的禿鷹蹲堂,則因此擴(kuò)大了地盤……這就是一個(gè)觸發(fā)機(jī)制,形成了一個(gè)觸發(fā)鏈贝淤。觀察者 模式可以完美地實(shí)現(xiàn)這里的鏈條形式柒竞。
2.2 缺點(diǎn)
觀察者模式需要考慮一下開發(fā)效率和運(yùn)行效率問題,一個(gè)被觀察者播聪,多個(gè)觀察者朽基,開發(fā) 和調(diào)試就會(huì)比較復(fù)雜,而且在Java中消息的通知默認(rèn)是順序執(zhí)行离陶,一個(gè)觀察者卡殼稼虎,會(huì)影響 整體的執(zhí)行效率。在這種情況下枕磁,一般考慮采用異步的方式躲查。
多級(jí)觸發(fā)時(shí)的效率更是讓人擔(dān)憂,大家在設(shè)計(jì)時(shí)注意考慮勾效。
2.3 使用場(chǎng)景
- 關(guān)聯(lián)行為場(chǎng)景各吨。
需要注意的是,關(guān)聯(lián)行為是可拆分的沦寂,而不是“組合”關(guān)系学密。
- 事件多級(jí)觸發(fā)場(chǎng)景。
- 跨系統(tǒng)的消息交換場(chǎng)景传藏,如消息隊(duì)列的處理機(jī)制腻暮。