摘要:為了幫助灰太狼擺脫被老婆平底鍋抽的悲劇,發(fā)起了解救灰太狼的行動(dòng),必須要知道觀察者模式。持有觀察者對(duì)象的集合。設(shè)計(jì)模式源碼下載
相信大家都有看過(guò)《喜洋洋與灰太狼》,說(shuō)的是灰太狼和羊族的“斗爭(zhēng)”,而每次的結(jié)果都是灰太狼一飛沖天,伴隨著一句“我還會(huì)回來(lái)的......”。為灰太狼感到悲哀,抓不到羊,在家也被老婆平底鍋虐待?;姨菫槭裁磿?huì)這么背?
很簡(jiǎn)單,灰太狼本身就有“暴露行蹤”的屬性,羊咩咩就能知曉灰太狼要干嘛,不背才怪呢。
為了幫助灰太狼擺脫被老婆平底鍋抽的悲劇,發(fā)起了“解救灰太狼”的行動(dòng),必須要知道觀察者模式。
一、觀察者模式 定義??觀察者模式又叫做發(fā)布-訂閱模式,定義了對(duì)象間一對(duì)多的依賴關(guān)系,使得當(dāng)對(duì)象狀態(tài)發(fā)生變化時(shí),所有依賴它的對(duì)象都會(huì)收到通知并且自動(dòng)更新自己。
特點(diǎn)??1)被觀察者需要持有一個(gè)或者多個(gè)觀察者對(duì)象。
??2)系統(tǒng)中一個(gè)模塊的變化,某些模塊也會(huì)跟隨著變化。
UML從上面的UML可以看出來(lái),觀察者模式設(shè)計(jì)到的角色有如下四個(gè):
??- 抽象被觀察者角色:定義了動(dòng)態(tài)增加、刪除以及通知觀察者對(duì)象的方法,職責(zé)就是管理和通知觀察者。持有觀察者對(duì)象的集合。
??- 具體被觀察者角色:一般繼承抽象被觀察者,實(shí)現(xiàn)自己本身的業(yè)務(wù)邏輯,當(dāng)狀態(tài)發(fā)生改變時(shí)發(fā)起通知。
??- 抽象觀察者角色:提供一個(gè)接口,定義了觀察者收到通知時(shí)更新自己的方法。
??- 具體觀察者角色:實(shí)現(xiàn)抽象觀察者接口,處理不同具體觀察者的不同業(yè)務(wù)邏輯。
二、實(shí)戰(zhàn)灰太狼具有被觀察者屬性,喜洋洋這些羊咩咩一直都在觀察者灰太狼,所以羊咩咩們是觀察者。OK,角色確定了,看看具體是怎么實(shí)現(xiàn)的...
抽象被觀察者代碼如下:
public abstract class Subject { /** * 觀察者對(duì)象的集合 */ private ListobserverList = new ArrayList<>(); /** * 登記觀察者 * * @param observer */ public void attach(Observer observer) { observerList.add(observer); System.out.println("增加了觀察者:" + observer.getName()); } /** * 刪除觀察者 * * @param observer */ public void dettach(Observer observer) { observerList.remove(observer); System.out.println("刪除了觀察者:" + observer.getName()); } /** * 通知所有觀察者 */ public void notifyObserver() { for (Observer observer : observerList) { observer.update("灰太狼要搞事情了"); } } }
灰太狼是具體被觀察者,繼承抽象被觀察者,代碼如下:
public class Wolf extends Subject { public void invade(){ System.out.println("灰太狼:我要搞事情了"); // 通知所有觀察者 notifyObserver(); } }
抽象觀察者代碼如下:
public interface Observer { String getName(); /** * 通知更新方法 * * @param msg */ public void update(String msg); }
喜羊羊是具體觀察者,實(shí)現(xiàn)抽象觀察者,代碼如下:
public class PleasantSheep implements Observer{ @Override public String getName() { return "喜羊羊"; } /** * 具體業(yè)務(wù)邏輯 */ @Override public void update(String msg) { System.out.println("喜羊羊收到通知:" + msg); } }
接下來(lái)看客戶端如何把觀察者模式跑起來(lái),代碼如下:
public class Client { public static void main(String[] args) { // 灰太狼--被觀察者 Wolf wolf = new Wolf(); // 喜羊羊--觀察者 Observer pleasantSheep = new PleasantSheep(); // 登記觀察者 wolf.attach(pleasantSheep); // 灰太狼入侵 wolf.invade(); } }
運(yùn)行客戶端代碼,結(jié)果如下:
增加了觀察者:喜羊羊灰太狼:我要搞事情了
喜羊羊收到通知:灰太狼要搞事情了
看到了吧,灰太狼這不是自找虐嗎!搞事情還要發(fā)通知,活該被平底鍋拍飛?;姨遣恢雇ㄖ讼惭蜓颍€通知了懶羊羊。
懶羊羊也是具體觀察者,代碼如下:
public class LazySheep implements Observer { @Override public String getName() { return "懶羊羊"; } @Override public void update(String msg) { System.out.println("懶羊羊收到通知:" + msg); } }
客戶端代碼如下:
public class Client { public static void main(String[] args) { // 灰太狼--被觀察者 Wolf wolf = new Wolf(); // 喜羊羊--觀察者 Observer pleasantSheep = new PleasantSheep(); // 登記觀察者 wolf.attach(pleasantSheep); // 懶羊羊--觀察者 Observer lazySheep = new LazySheep(); // 登記觀察者 wolf.attach(lazySheep); // 灰太狼入侵 wolf.invade(); } }
上面客戶端代碼創(chuàng)建了一個(gè)懶羊羊觀察者,添加了觀察者集合中,這樣懶羊羊也會(huì)受到通知,運(yùn)行結(jié)果如下:
增加了觀察者:喜羊羊增加了觀察者:懶羊羊
灰太狼:我要搞事情了
喜羊羊收到通知:灰太狼要搞事情了
懶羊羊收到通知:灰太狼要搞事情了
那如何幫助灰太狼擺脫這個(gè)命運(yùn)呢,把觀察者從集合中移除就OK了,代碼如下:
public class Client { public static void main(String[] args) { // 灰太狼--被觀察者 Wolf wolf = new Wolf(); // 喜羊羊--觀察者 Observer pleasantSheep = new PleasantSheep(); // 登記觀察者 wolf.attach(pleasantSheep); // 懶羊羊--觀察者 Observer lazySheep = new LazySheep(); // 登記觀察者 wolf.attach(lazySheep); // 灰太狼入侵 wolf.invade(); // 刪除觀察者 wolf.dettach(pleasantSheep); wolf.invade(); } }
再次運(yùn)行客戶端,結(jié)果如下:
增加了觀察者:喜羊羊增加了觀察者:懶羊羊
灰太狼:我要搞事情了
喜羊羊收到通知:灰太狼要搞事情了
懶羊羊收到通知:灰太狼要搞事情了
刪除了觀察者:喜羊羊
灰太狼:我要搞事情了
懶羊羊收到通知:灰太狼要搞事情了
可以看到,把喜羊羊從觀察者集合中移除了,它就不會(huì)再收到通知。
三、觀察者模式的優(yōu)缺點(diǎn) 優(yōu)點(diǎn)1)觀察者和被觀察者之間抽象耦合。觀察者模式容易擴(kuò)展,被觀察者只持有觀察者集合,并不需要知道具體觀察者內(nèi)部的實(shí)現(xiàn)。
2)對(duì)象之間的保持高度的協(xié)作。當(dāng)被觀察者發(fā)生變化時(shí),所有被觀察者都會(huì)通知到,然后做出相應(yīng)的動(dòng)作。
缺點(diǎn)1)如果觀察者太多,被觀察者通知觀察者消耗的時(shí)間很多,影響系統(tǒng)的性能。
2)當(dāng)觀察者集合中的某一觀察者錯(cuò)誤時(shí)就會(huì)導(dǎo)致系統(tǒng)卡殼,因此一般會(huì)采用異步方式。
四、比較跟代理模式對(duì)比:觀察者模式和代理模式主要區(qū)別在它們功能不一樣,觀察者模式強(qiáng)調(diào)的是被觀察者反饋結(jié)果,而代理模式是同根負(fù)責(zé)做同樣的事情。
總結(jié)在Java中已經(jīng)提供了Observable類以及一個(gè)Observer接口,也就是說(shuō)Java已經(jīng)實(shí)現(xiàn)了觀察者模式的定義,可看出觀察者模式在程序系統(tǒng)中的使用率是很高的,不單是Java,Android中也經(jīng)??吹接^察者模式的運(yùn)用,比如OnClickListener,Rxjava等。下一篇會(huì)補(bǔ)上屬于創(chuàng)建型模式的原型模式,下回分解,再見(jiàn)。
設(shè)計(jì)模式Java源碼GitHub下載:https://github.com/jetLee92/DesignPattern
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67812.html
摘要:觀察者模式的使用場(chǎng)景比如你微博關(guān)注了一個(gè)人,那么這個(gè)人發(fā)布的微博就會(huì)推送到你這。 Java設(shè)計(jì)模式之觀察者模式 一直想寫一篇學(xué)習(xí)觀察者模式的總結(jié)沒(méi)有契機(jī),今天學(xué)習(xí)阻塞隊(duì)列的原理時(shí)候看到在實(shí)現(xiàn)生產(chǎn)者消費(fèi)者的時(shí)候用到了通知模式,就是所謂的觀察者模式,正好順便整理一下。 1. 簡(jiǎn)介 觀察者模式定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更...
摘要:實(shí)際上,設(shè)計(jì)模式就是通過(guò)面向?qū)ο蟮奶匦?,將這些角色解耦觀察者模式本質(zhì)上就是一種訂閱發(fā)布的模型,從邏輯上來(lái)說(shuō)就是一對(duì)多的依賴關(guān)系。在添加一個(gè)觀察者時(shí),把被主題被觀察者對(duì)象以構(gòu)造函數(shù)的形式給傳入了觀察者。 每個(gè)角色都對(duì)應(yīng)這一個(gè)類,比如觀察者模式,觀察者對(duì)應(yīng)著觀察者類,被觀察者對(duì)應(yīng)著被觀察者類。實(shí)際上,設(shè)計(jì)模式就是通過(guò)面向?qū)ο蟮奶匦裕瑢⑦@些角色解耦 觀察者模式本質(zhì)上就是一種訂閱 / 發(fā)布的模...
摘要:咦這一層一層上報(bào)就涉及到這次的責(zé)任鏈模式。責(zé)任鏈模式和觀察者模式存在一個(gè)共同點(diǎn),就是傳遞責(zé)任鏈模式是一級(jí)一級(jí)的傳遞,形成一條鏈,鏈節(jié)點(diǎn)處理者之間是存在傳遞關(guān)系的。這是責(zé)任鏈模式和觀察者模式的區(qū)別,也是責(zé)任鏈模式的核心。 今天來(lái)說(shuō)說(shuō)程序員小猿和產(chǎn)品就關(guān)于需求發(fā)生的故事。前不久,小猿收到了產(chǎn)品的需求。 產(chǎn)品經(jīng)理:小猿,為了迎合大眾屌絲用戶的口味,我們要放一張圖,要露點(diǎn)的。 小猿:........
閱讀 3078·2021-10-12 10:12
閱讀 3158·2021-09-22 16:04
閱讀 3351·2019-08-30 15:54
閱讀 2681·2019-08-29 16:59
閱讀 3015·2019-08-29 16:08
閱讀 927·2019-08-29 11:20
閱讀 3558·2019-08-28 18:08
閱讀 749·2019-08-26 13:43