觀察者模式(Observer),又叫發(fā)布-訂閱模式(Publish/Subscribe)开泽,定義了一種一對(duì)多的依賴關(guān)系牡拇,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽某一個(gè)主題對(duì)象。這個(gè)主體對(duì)象在狀態(tài)發(fā)生變化時(shí)穆律,會(huì)通知所有觀察者對(duì)象惠呼,使它們能夠自動(dòng)更新自己。
適用場(chǎng)景
當(dāng)一個(gè)對(duì)象的改變需要同時(shí)改變其他對(duì)象的時(shí)候峦耘,而且它不知道具體有多少對(duì)象有待改變時(shí)罢杉,應(yīng)該考慮使用觀察者模式。一個(gè)抽象模型有兩個(gè)方面贡歧,其中一方面依賴于另一方面滩租,這時(shí)用觀察者模式可以將這兩者封裝在獨(dú)立的對(duì)象中使它們各自的獨(dú)立的改變和復(fù)用赋秀。
優(yōu)點(diǎn)
- 觀察者模式在被觀察者和觀察者之間建立一個(gè)抽象的耦合。
- 觀察者模式支持廣播通訊律想。
缺點(diǎn)
- 如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話猎莲,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。
- 如果在被觀察者之間有循環(huán)依賴的話技即,被觀察者會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用著洼,導(dǎo)致系統(tǒng)崩潰。在使用觀察者模式是要特別注意這一點(diǎn)而叼。
- 如果對(duì)觀察者的通知是通過(guò)另外的線程進(jìn)行異步投遞的話身笤,系統(tǒng)必須保證投遞是以自恰的方式進(jìn)行的。
- 雖然觀察者模式可以隨時(shí)使觀察者知道所觀察的對(duì)象發(fā)生了變化葵陵,但是觀察者模式?jīng)]有相應(yīng)的機(jī)制使觀察者知道所觀察的對(duì)象是怎么發(fā)生變化的液荸。
UML結(jié)構(gòu)圖
源碼
Subject:主題或叫抽象通知者
/**
* 主題或叫抽象通知者
*
* Created by zhenguo on 11/29/14.
*/
public abstract class Subject {
private List<Observer> observers = new ArrayList<Observer>();
/**
* 增加觀察者
* @param observer
*/
public void attach(Observer observer) {
observers.add(observer);
}
/**
* 移除觀察者
* @param observer
*/
public void detach(Observer observer) {
observers.remove(observer);
}
/**
* 通知所有觀察者
*/
public void notifyAllObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
Observer:抽象觀察者
/**
* 抽象觀察者
*
* Created by zhenguo on 11/29/14.
*/
public abstract class Observer {
public abstract void update();
}
ConcreteSubject:具體主題或具體通知者
/**
* 具體主題或具體通知者
*
* Created by zhenguo on 11/29/14.
*/
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
ConcreteObserver:具體觀察者
/**
* 具體觀察者
*
* Created by zhenguo on 11/29/14.
*/
public class ConcreteObserver extends Observer {
private String name;
private ConcreteSubject subject;
public ConcreteObserver(String name, ConcreteSubject subject) {
this.name = name;
this.subject = subject;
}
@Override
public void update() {
System.out.println("觀察者 " + name + " 的狀態(tài)是 " + subject.getState());
}
public ConcreteSubject getSubject() {
return subject;
}
public void setSubject(ConcreteSubject subject) {
this.subject = subject;
}
}
Client:客戶端調(diào)用
/**
* 客戶端調(diào)用
* 觀察者模式(Observer),又叫發(fā)布-訂閱模式(Publish/Subscribe)脱篙,定義了一種一對(duì)多的依賴關(guān)系娇钱,讓多個(gè)觀察者對(duì)象
* 同時(shí)監(jiān)聽某一個(gè)主題對(duì)象。這個(gè)主體對(duì)象在狀態(tài)發(fā)生變化時(shí)绊困,會(huì)通知所有觀察者對(duì)象文搂,使它們能夠自動(dòng)更新自己。
*
* Created by zhenguo on 11/29/14.
*/
public class Client {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
subject.attach(new ConcreteObserver("A", subject));
subject.attach(new ConcreteObserver("B", subject));
subject.attach(new ConcreteObserver("C", subject));
subject.setState("XYZ");
subject.notifyAllObservers();
}
}
設(shè)計(jì)模式系列:
創(chuàng)建型 | 結(jié)構(gòu)型 | 行為型 |
---|---|---|
工廠方法 簡(jiǎn)單工廠 抽象工廠 建造者模式 單例模式 原型模式 |
組合模式 外觀模式 橋接模式 代理模式 享元模式 適配器模式 裝飾模式 |
策略模式 模板方法 狀態(tài)模式 觀察者模式 備忘錄模式 迭代器模式 命令模式 職責(zé)鏈模式 解釋器模式 訪問者模式 中介者模式 |