觀察者模式
- 定義對(duì)象間一種一對(duì)多的依賴關(guān)系,使得每當(dāng)一個(gè)對(duì)象改變狀態(tài)冻辩,則所有依賴于它的對(duì)象都會(huì)得到通知并自動(dòng)更新猖腕,也叫做發(fā)布訂閱模式Publish/Subscribe,屬于行為型模式
應(yīng)用場(chǎng)景
- 消息通知里面:郵件通知恨闪、廣播通知倘感、微信朋友圈、微博私信等咙咽,就是監(jiān)聽觀察事件
- 當(dāng)一個(gè)對(duì)象的改變需要同時(shí)改變其它對(duì)象老玛,且它不知道具體有多少對(duì)象有待改變的時(shí)候,考慮使用觀察者模式
角色
- Subject主題:持有多個(gè)觀察者對(duì)象的引用犁珠,抽象主題提供了一個(gè)接口可以增加和刪除觀察者對(duì)象逻炊;有一個(gè)觀察者數(shù)組,并實(shí)現(xiàn)增犁享、刪及通知操作
- Observer抽象觀察者:為具體觀察者定義一個(gè)接口余素,在得到主題的通知時(shí)更新自己
- ConcreteSubject具體主題:將有關(guān)狀態(tài)存入具體觀察者對(duì)象,在具體主題內(nèi)部狀態(tài)改變時(shí)炊昆,給所有登記過的觀察者發(fā)出通知
- ConcreteObserver具體觀察者:實(shí)現(xiàn)抽象觀察者角色所要求的更新接口桨吊,以便使本身的狀態(tài)與主題的狀態(tài)保持一致
觀察者模式
業(yè)務(wù)需求
小滴課堂-老王,技術(shù)比較厲害凤巨,因此上班不想那么辛苦视乐,領(lǐng)導(dǎo)又在周圍,所以選了個(gè)好位置敢茁,方便監(jiān)聽老板的到來(lái)佑淀,
當(dāng)領(lǐng)導(dǎo)即將出現(xiàn)時(shí)老王可以立馬觀察到,趕緊工作彰檬。
用觀察者模式幫助老王實(shí)現(xiàn)這個(gè)需求
編碼:
信息發(fā)布者
public class Subject {
private List<Observer> observerList = new ArrayList<>();
/**
* 新增觀察者
* @param observer
*/
public void addObserver(Observer observer){
this.observerList.add(observer);
}
/**
*刪除觀察者
* @param observer
*/
public void deleteObserver(Observer observer){
this.observerList.remove(observer);
}
public void notifyAllObserver(){
for(Observer observer:this.observerList){
observer.update();
}
}
}
抽象觀察者:
public interface Observer {
/**
* 觀察到消息后進(jìn)行的操作伸刃,就是響應(yīng)
*/
void update();
}
信息發(fā)布者:
public class BossConcreteSubject extends Subject {
public void doSomething(){
System.out.println("老板完成自己的工作");
//還有其他操作
System.out.println("視察公司工作情況");
super.notifyAllObserver();
}
}
具體消費(fèi)者
public class LWConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("老王發(fā)現(xiàn)領(lǐng)導(dǎo)到來(lái),暫停在線摸魚逢倍,回歸工作");
}
}
具體消費(fèi)者2:
public class AnnaConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("Anna小姐姐發(fā)現(xiàn)領(lǐng)導(dǎo)到來(lái)捧颅,暫停在線摸魚,回歸工作");
}
}
Main函數(shù)
public class Main {
public static void main(String[] args) {
//創(chuàng)建一個(gè)主題较雕,老板
BossConcreteSubject subject = new BossConcreteSubject();
//創(chuàng)建觀察者碉哑,就是摸魚的同事
Observer lwObserver = new LWConcreteObserver();
//創(chuàng)建觀察者,就是摸魚的同事
Observer annaObserver = new AnnaConcreteObserver();
//建立對(duì)應(yīng)的關(guān)系,老板這個(gè)主題被同事進(jìn)行觀察
subject.addObserver(lwObserver);
subject.addObserver(annaObserver);
//主題開始活動(dòng)扣典,里面會(huì)通知觀察者(相當(dāng)于發(fā)布消息)
subject.doSomething();
}
}
執(zhí)行結(jié)果:
老板完成自己的工作
視察公司工作情況
老王發(fā)現(xiàn)領(lǐng)導(dǎo)到來(lái)妆毕,暫停在線摸魚,回歸工作
Anna小姐姐發(fā)現(xiàn)領(lǐng)導(dǎo)到來(lái)贮尖,暫停在線摸魚设塔,回歸工作
優(yōu)點(diǎn)
- 降低了目標(biāo)與觀察者之間的耦合關(guān)系,目標(biāo)與觀察者之間建立了一套觸發(fā)機(jī)制
- 觀察者和被觀察者是抽象耦合的
缺點(diǎn)
- 觀察者和觀察目標(biāo)之間有循環(huán)依賴的話远舅,會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用闰蛔,可能導(dǎo)致系統(tǒng)崩潰
- 一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間
觀察者設(shè)計(jì)模式UML