摘要:簡(jiǎn)介學(xué)習(xí)本篇博文,我們知道在什么場(chǎng)景下使用觀察者模式。觀察者模式給我們?cè)诮窈箝_發(fā)中什么思想。為什么需要觀察者模式從定義中我們可以知道觀察者模式當(dāng)對(duì)象改變時(shí),其他依賴的對(duì)象都會(huì)收到改變信息的狀態(tài)。
簡(jiǎn)介
1.學(xué)習(xí)本篇博文,我們知道在什么場(chǎng)景下使用觀察者模式。
2.觀察者模式的優(yōu)缺點(diǎn)。
3.觀察者模式給我們?cè)诮窈箝_發(fā)中什么思想。
某家科技公司目前在開發(fā)一個(gè)項(xiàng)目,設(shè)計(jì)小組需要上報(bào)項(xiàng)目的進(jìn)度給部門經(jīng)理,主要有兩個(gè)模塊更新原有的業(yè)務(wù)模塊進(jìn)度和添加新業(yè)務(wù)的模塊完成進(jìn)度。
那么部門經(jīng)理需要什么途徑能最快的得到進(jìn)度的信息呢?或者可能是項(xiàng)目總監(jiān)也想?yún)⑴c,去獲取到最新的進(jìn)展情況呢?我們改如何去考慮這個(gè)業(yè)務(wù)呢?
很多時(shí)候我們就會(huì)想到繼承去解決這一情況,畢竟OO編寫思想時(shí)刻影響這一我們,但是如果某天項(xiàng)目經(jīng)理出差了,他不想看項(xiàng)目進(jìn)度了,那我們又改怎么辦呢?
我們能不能就是設(shè)計(jì)一個(gè)業(yè)務(wù),讓能想知道該進(jìn)度的人,不管什么時(shí)候,只要有開發(fā)者上報(bào)進(jìn)度的時(shí)候就一下他就得到進(jìn)度的信息,而他無(wú)需去關(guān)系這個(gè)過(guò)程。
你是否能想到合適的解決方案呢?
答案就在下文中,你準(zhǔn)備好了嗎?
問(wèn)題 什么是觀察者模式?觀察者模式定義一系列對(duì)象之間的一對(duì)多關(guān)系,當(dāng)一個(gè)對(duì)象改變、更新狀態(tài)時(shí),依賴它的都會(huì)收到通知改變或者更新。
為什么需要觀察者模式?從定義中我們可以知道觀察者模式當(dāng)對(duì)象改變時(shí),其他依賴的對(duì)象都會(huì)收到改變信息的狀態(tài)。
從本例分析項(xiàng)目經(jīng)理想知道進(jìn)度情況,他只需要綁定進(jìn)度,他就可以知道進(jìn)度信息了,而無(wú)需關(guān)心如何操作,如果再增加一個(gè)想知道進(jìn)度信息老板呢?也很容易,也讓老板綁定進(jìn)度信息數(shù)據(jù)就好了,不想知道的時(shí)候就解除綁定,就不在獲取進(jìn)度信息了。
所以在本案例場(chǎng)景中,觀察者是我們這個(gè)場(chǎng)景非常合適的設(shè)計(jì)。
如何實(shí)現(xiàn)觀察者模式? 自定義觀察者模式 實(shí)現(xiàn)如下我們先來(lái)看一下這個(gè)UML類圖進(jìn)行分析
具體實(shí)現(xiàn)步驟
1.構(gòu)造一個(gè)主題Subject或者是一個(gè)被觀察者Observeable,這是一個(gè)接口或者是抽象類
public interface Subject { //注冊(cè)觀察者 void registerObserver(Observer observe); //解除綁定觀察者 void unRegisterObserver(Observer observe); //更新數(shù)據(jù) void notifyObservers(); }
2.構(gòu)建一個(gè)被觀察者實(shí)現(xiàn)該主題接口如本例的 DevelopmentProgressData.class,這里是進(jìn)度信息數(shù)據(jù)
在registerObserver(Observer o);//方法中將觀察者添加到注冊(cè)列表中
在unRegisterObserve(Observer o);//刪除觀察者
public class DevelopmentProgressData implements Subject { @Override public void registerObserver(Observer observer) { //將觀察者添加到列表中 arrayObserve.add(observer); } @Override public void unRegisterObserver(Observer observer) { int i = arrayObserve.indexOf(observer); if (i >= 0) { //將觀察者從列表中解除 arrayObserve.remove(i); } } //通知所以觀察者數(shù)據(jù)更新了 @Override public void notifyObservers() { for (int i = 0; i < arrayObserve.size(); i++) { Observer o = (Observer) arrayObserve.get(i); o.update(completeProgress, updateProgress); } } }
3.構(gòu)建一個(gè)觀察者接口Observer
public interface Observer { //更新數(shù)據(jù) void update(int completeProgress, int updateProgress); }
4.可構(gòu)建一個(gè)展示數(shù)據(jù)的接口(可忽略)
有展示數(shù)據(jù)的方法,觀察者要實(shí)現(xiàn)這個(gè)方法 查看本例的 DisplaySchedule
public interface DisplaySchedule { void display(); }
5.定義觀察者(模擬該類就是產(chǎn)品經(jīng)理觀察者),需實(shí)現(xiàn)接口Observes、DisplaySchedule(可忽略),
<1>、將主題Subject設(shè)置為觀察者的屬性,并將其作為觀察者的構(gòu)造函數(shù)如 ProductManagerObserver.class
調(diào)用 developmentProgressSubject.registerObserver(this);將觀察者注冊(cè)到觀察列表中
public class ProductManagerObserver implements Observer, DisplaySchedule { private int completeProgress;//完成進(jìn)度 private int updateProgress;//更新進(jìn)度 //將主題當(dāng)成觀察者的屬性 private Subject developmentProgressSubject; public ProductManagerObserver(Subject developmentProgressSubject) { this.developmentProgressSubject = developmentProgressSubject; //注冊(cè)該觀察者 developmentProgressSubject.registerObserver(this); } @Override public void display() { System.out.println("產(chǎn)品經(jīng)理管理者顯示當(dāng)前數(shù)據(jù) 完成進(jìn)度為: " + completeProgress + "更新修改進(jìn)度為:" + updateProgress); } @Override public void update(int completeProgress, int updateProgress) { this.completeProgress = completeProgress; this.updateProgress = updateProgress; display(); } }
測(cè)試
RunTest.class
public class RunTest { public static void main(String[] args) { DevelopmentProgressData developmentProgressData = new DevelopmentProgressData(); ProductManagerObserver productManagerObserver = new ProductManagerObserver(developmentProgressData); ProjectManagerObserver projectManagerObserver = new ProjectManagerObserver(developmentProgressData); developmentProgressData.setCurrentData(34, 45); //當(dāng)項(xiàng)目經(jīng)理出差了,不觀察項(xiàng)目進(jìn)度了就取消訂閱了 developmentProgressData.unRegisterObserver(projectManagerObserver); //當(dāng)前只有產(chǎn)品經(jīng)理獲取到數(shù)據(jù) developmentProgressData.setCurrentData(46, 90); } }
輸出結(jié)果
C:Javajdk1.8.0_161in... 產(chǎn)品經(jīng)理管理者顯示當(dāng)前數(shù)據(jù) 完成進(jìn)度為: 34更新修改進(jìn)度為:45 項(xiàng)目管理真顯示當(dāng)前數(shù)據(jù)完成進(jìn)度為: 34更新修改進(jìn)度為:45 產(chǎn)品經(jīng)理管理者顯示當(dāng)前數(shù)據(jù) 完成進(jìn)度為: 46更新修改進(jìn)度為:90 Process finished with exit code 0根據(jù)java.util.observerable包下的Observerable.class實(shí)現(xiàn)觀察者模式功能 實(shí)現(xiàn)如下
具體實(shí)現(xiàn)步驟
1.首先觀察者需要實(shí)現(xiàn)java.util.Observer,然后將其被觀察者=>java.util.Observaerable作為其觀察者的構(gòu)造函數(shù)
<1>、通過(guò)observeable.addObserver(this)添加觀察者
public class BossMngObserver implements Observer, DisplayIllustrate { private Observable observable; private int valuableProductNum; //庫(kù)存有貴重產(chǎn)品 private int normalProductNum; //普通產(chǎn)品 public BossMngObserver(Observable observable) { this.observable = observable; observable.addObserver(this); } @Override public void disPlay() { System.out.println("總經(jīng)理觀察數(shù)據(jù)改變:貴重產(chǎn)品數(shù)量: " + valuableProductNum + "普通產(chǎn)品數(shù)量: " + normalProductNum); } //<2>、實(shí)現(xiàn) Observer更新數(shù)據(jù)方法 //看本例的包下的observe的三個(gè)類 @Override public void update(Observable o, Object arg) { if (o instanceof InventoryData) { InventoryData inventoryData = (InventoryData) o; this.valuableProductNum = inventoryData.getValuableProductNum(); this.normalProductNum = inventoryData.getNormalProductNum(); disPlay(); } } }
2.被觀察者需要繼承java.util.Observerable,
<1>、然后先調(diào)用setChanged()方法
<2>、在進(jìn)行調(diào)用notifyObserves()更新數(shù)據(jù)
public class InventoryData extends Observable { private int valuableProductNum; //庫(kù)存有貴重產(chǎn)品 private int normalProductNum; //普通產(chǎn)品 public void setCurrentData(int valuableProductNum, int normalProductNum) { this.valuableProductNum = valuableProductNum; this.normalProductNum = normalProductNum; statusChange(); } private void statusChange() { //先調(diào)用 setChanged(); setChanged(); notifyObservers(); } }
測(cè)試
3.Test.class
public class Test { public static void main(String[] args) { InventoryData inventoryData = new InventoryData(); ValuableInfoMngObserver io = new ValuableInfoMngObserver(inventoryData); //io.deleteObserve(); inventoryData.setCurrentData(20, 30); NormalInfoMngObserver no = new NormalInfoMngObserver(inventoryData); //no.deleteObserver(); inventoryData.setCurrentData(15, 27); BossMngObserver bossMngObserver = new BossMngObserver(inventoryData); inventoryData.setCurrentData(10, 50); } }下載
觀察者模式案例代碼
總結(jié)觀察者模式的讓我們知道了在設(shè)計(jì)開發(fā)的時(shí)候一定要“多用組合,少用繼承”。
我們?cè)O(shè)計(jì)開發(fā)是應(yīng)該是針對(duì)接口變成,而不針對(duì)實(shí)現(xiàn)編程。
在java.util.*下的Observer和Observable可以實(shí)現(xiàn)觀察者,但是Observable是一個(gè)類,這樣我們是不違背了“多用組合少用繼承”的OO編程思想,是的沒錯(cuò)在java.util.Observable類違背了該規(guī)則。
我的GitHub博客 設(shè)計(jì)模式大家可以進(jìn)入這里學(xué)習(xí)設(shè)計(jì)模式
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76995.html
摘要:關(guān)鍵概念理解觀察者設(shè)計(jì)模式中主要區(qū)分兩個(gè)概念觀察者指觀察者對(duì)象,也就是消息的訂閱者被觀察者指要觀察的目標(biāo)對(duì)象,也就是消息的發(fā)布者。 原文首發(fā)于微信公眾號(hào):jzman-blog,歡迎關(guān)注交流! 最近補(bǔ)一下設(shè)計(jì)模式相關(guān)的知識(shí),關(guān)于觀察者設(shè)計(jì)模式主要從以下幾個(gè)方面來(lái)學(xué)習(xí),具體如下: 什么是觀察者設(shè)計(jì)模式 關(guān)鍵概念理解 通知觀察者的方式 觀察者模式的實(shí)現(xiàn) 觀察者模式的優(yōu)缺點(diǎn) 使用場(chǎng)景 下面...
摘要:觀察者模式與發(fā)布訂閱的區(qū)別在模式中,知道,同時(shí)還保留了的記錄。發(fā)布者訂閱者在大多情況下是異步方式使用消息隊(duì)列。圖片源于網(wǎng)絡(luò)侵權(quán)必刪如果以結(jié)構(gòu)來(lái)分辨模式,發(fā)布訂閱模式相比觀察者模式多了一個(gè)中間件訂閱器,所以發(fā)布訂閱模式是不同于觀察者模式的。 學(xué)習(xí)了一段時(shí)間設(shè)計(jì)模式,當(dāng)學(xué)到觀察者模式和發(fā)布訂閱模式的時(shí)候遇到了很大的問(wèn)題,這兩個(gè)模式有點(diǎn)類似,有點(diǎn)傻傻分不清楚,博客起因如此,開始對(duì)觀察者和發(fā)布...
摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個(gè)角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個(gè)角色,還有第三個(gè)角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長(zhǎng)時(shí)間的 菜鳥程序員 ,我好像還沒有寫過(guò)一篇關(guān)于設(shè)計(jì)模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計(jì)模式在從頭學(xué)習(xí)一遍,不然都對(duì)不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...
摘要:總結(jié)一下從表面上看觀察者模式里,只有兩個(gè)角色觀察者被觀察者而發(fā)布訂閱模式,卻不僅僅只有發(fā)布者和訂閱者兩個(gè)角色,還有第三個(gè)角色經(jīng)紀(jì)人存在。參考鏈接觀察者模式發(fā)布訂閱模式 做了這么長(zhǎng)時(shí)間的 菜鳥程序員 ,我好像還沒有寫過(guò)一篇關(guān)于設(shè)計(jì)模式的博客...咳咳...意外,純屬意外。所以,我決定,從這一刻起,我要把設(shè)計(jì)模式在從頭學(xué)習(xí)一遍,不然都對(duì)不起我這 菜鳥 的身份。那這次,就從觀察者模式開始好啦...
摘要:或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱,但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。參考文章訂閱發(fā)布模式和觀察者模式真的不一樣 首選我們需要先了解兩者的定義和實(shí)現(xiàn)的方式,才能更好的區(qū)分兩者的不同點(diǎn)。 或許以前認(rèn)為訂閱發(fā)布模式是觀察者模式的一種別稱,但是發(fā)展至今,概念已經(jīng)有了不少區(qū)別。 訂閱發(fā)布模式 在軟件架構(gòu)中,發(fā)布-訂閱是一種消息范式,消息的發(fā)送者(稱為發(fā)布者)不會(huì)將消息直接發(fā)送給特...
摘要:為了幫助灰太狼擺脫被老婆平底鍋抽的悲劇,發(fā)起了解救灰太狼的行動(dòng),必須要知道觀察者模式。持有觀察者對(duì)象的集合。設(shè)計(jì)模式源碼下載 相信大家都有看過(guò)《喜洋洋與灰太狼》,說(shuō)的是灰太狼和羊族的斗爭(zhēng),而每次的結(jié)果都是灰太狼一飛沖天,伴隨著一句我還會(huì)回來(lái)的......。為灰太狼感到悲哀,抓不到羊,在家也被老婆平底鍋虐待?;姨菫槭裁磿?huì)這么背? 很簡(jiǎn)單,灰太狼本身就有暴露行蹤的屬性,羊咩咩就能知曉灰太...
閱讀 2922·2021-11-24 09:39
閱讀 3599·2021-11-22 13:54
閱讀 3409·2021-11-16 11:45
閱讀 2432·2021-09-09 09:33
閱讀 3194·2019-08-30 15:55
閱讀 1290·2019-08-29 15:40
閱讀 920·2019-08-29 15:19
閱讀 3396·2019-08-29 15:14