觀察者(Observer)
[TOC]
定義
觀察者模式也是一種運(yùn)用非常廣泛的模式了禁荸,Subject(主題)和Obesever(觀察者)已經(jīng)很好的闡述了什么是觀察者模式跟匆,就好像報(bào)社雪猪,誰訂閱
了報(bào)紙绰寞,報(bào)只要在新聞有更新的時候就會定期給訂閱報(bào)紙的人發(fā)放報(bào)紙撮竿,而如果有一天纤泵,出了某頭條的應(yīng)用骆姐,某人使用這個APP來查看每天自己感興趣的新聞,從而去報(bào)社取消了訂閱
報(bào)紙捏题,那么當(dāng)報(bào)社出版新報(bào)紙的時候玻褪,就不再給這個人發(fā)送報(bào)紙了,那么這種關(guān)系公荧,就稱為觀察者带射。
- 術(shù)語定義
觀察者模式描述的是一種對象之間一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變的時候循狰,那么所有依賴者對象都會收到通知窟社,然后做各自的具體實(shí)現(xiàn)
coding
/**
* 主題接口,包括注冊绪钥,移除和通知觀察者
* @author Done
* @date 2017/12/6
*/
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObserver(Object data);
}
/**
* 觀察者接口灿里,再收到通知的時候,主題對象會去調(diào)用此接口程腹,
* 而具體實(shí)現(xiàn)類(觀察者)去做各自的實(shí)現(xiàn)
* @author Done
* @date 2017/12/6
* Created by Done on 2017/12/6.
*/
public interface Observer {
void onUpdate(Object data);
}
就這么簡單的兩個接口匣吊,但是卻完成了一種很好的程序架構(gòu)——松耦合
彼此不需要知道彼此具體的實(shí)現(xiàn)但仍然可以進(jìn)行交互
這也是本設(shè)計(jì)模式的設(shè)計(jì)原則核心——為了交互對象之間的松耦合而努力。
松耦合的設(shè)計(jì)之所以能讓我們建立有彈性的OO系統(tǒng)寸潦,能夠應(yīng)對變化缀去,是因?yàn)?code>對象之間的互相依賴降到了最低
OK,結(jié)合現(xiàn)實(shí)生活開始我們的代碼甸祭,首先咱們熟知的手撕對象:產(chǎn)品(ProductManager)和我們自己缕碎,兩個工種作為我們的觀察者對象,我們隨時恭候BOSS的各項(xiàng)指令
public class ProductManager implements Observer {
@Override
public void onUpdate(Object data) {
System.out.println("Project Manager receive news:" + data.toString());
}
}
public class Coder implements Observer {
@Override
public void onUpdate(Object data) {
System.out.println("coder receive news:" + data.toString());
}
}
作為觀察者池户,肯定必須先實(shí)現(xiàn)咱們之前提到的Observer接口咏雌,接收來自BOSS的指令凡怎,該干啥干啥,這里接口方法就簡單定義成onUpdate了哈~
那么接下來是咱們的BOSS赊抖,發(fā)號施令者统倒,代碼如下:
public class Leader implements Subject {
private List<Observer> observers;
public Leader() {
observers = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver(Object data) {
for (Observer observer : observers) {
observer.onUpdate(data);
}
}
}
同樣作為咱們的Subject主體,這里用List來存儲咱們的觀察者們氛雪,leader類實(shí)現(xiàn)Subject接口房匆,分別是注冊觀察者
void registerObserver(Observer observer);
移除觀察者
void removeObserver(Observer observer);
最后是咱們的通知觀察者
void notifyObserver(Object data);
OK,能者多勞嘛,咱們Leader類身為leader更應(yīng)該以身作則报亩,比較能干嘛浴鸿。。弦追。
完成編碼岳链,進(jìn)入咱們的run測試階段
public static void main(String[] args) {
Leader leader = new Leader();
Coder coder = new Coder();
ProjectManager projectManager = new ProjectManager();
leader.registerObserver(coder);
leader.registerObserver(projectManager);
leader.notifyObserver("Today is a holiday!");
System.out.println("now leader remove project manager!");
leader.removeObserver(projectManager);
leader.notifyObserver("Overnight overtime today!");
}
輸出:
coder receive news:Today is a holiday!
Project Manager receive news:Today is a holiday!
now leader remove project manager!
coder receive news:Work overtime today!
毋需多說,你懂的
話說JDK里面java.util包下面有這個模式劲件,可見此模式的普遍適用性和實(shí)用性掸哑,沒事大家可以參考一波,這里就不一一列舉了零远,不過和以上所述有一點(diǎn)初入的地方就是JDK中的Observable是一個類苗分,不是接口,你如果想要使用原生的觀察者牵辣,就得繼承這個類俭嘁,那么就限制了你的觀察者對象的復(fù)用潛力,稍微違背了我們那么一丟丟"增加復(fù)用潛力"服猪,“多用組合,少用繼承”
的設(shè)計(jì)動機(jī)哈~
感興趣的同學(xué)可以去參考一波JDK源碼