<!-- more -->
本文原創地址,我的博客
:https://jsbintask.cn/2019/04/15/designpattern/observer/(食用效果最佳),轉載請註明出處!
前言
觀察者模式定義了對象間的一種一對多依賴關係,當一個對象狀態發生改變時,觀察者們都可以做出相應的更新,使得系統更易於擴展!代碼地址:
https://github.com/jsbintask22/design-pattern-learning
案例
- 小麗長得很漂亮,"天生麗質難自棄", 是一個不折不扣的"女神"。
- 小麗身邊有很多”備胎“,他們通過各種方式添加了小麗的微信,“小豪,小吳”都是其中之一。
- 小麗總是會在朋友圈發佈自己的各種生活狀態。
- ”備胎們“總是及時並且積極地和女神互動!
- 小麗發現”備胎“小豪不愛互動了,於是刪除了“備胎”小豪的微信。
- 小豪發現自己看不了女神動態了。最終死心!
- 小麗認識了新“備胎”小李,於是小李也添加了女神微信。
- 小麗發佈自己的朋友圈動態,小李也開始了互動!
上面這個過程我們可以抽象出來兩個主題,女神小麗
,備胎小豪,小吳,小李
,我們用代碼模擬這個追女神的過程。
代碼實現
V1.0
Beauty
代表女神,LittleBoy
表示備胎,他們時刻在關注着女神的朋友圈,希望獲得互動,代碼實現如下:
public class App {
public static void main(String[] args) throws Exception{
Beauty beauty = new Beauty();
// 成功添加了女神微信
LittleBoy littleBoy = new LittleBoy(beauty);
// 開始查看女神朋友圈
littleBoy.start();
// 5s後,女神發佈了朋友圈。
Thread.sleep(5000L);
beauty.publishWechat();
System.in.read();
}
}
運行結果如下:
嗯!似乎很完美! 美中不足的是好像LittleBoy
的run方法一直在輪詢查看女神朋友圈,它沒辦法做自己的事情了:
這樣下去很快他就會失去和女神互動的耐心! 所以我們稍微修改下,讓這段代碼看起來更加”智能”。
V2.0
爲了不讓LittleBoy
一直輪詢查看女神狀態,我們可以修改爲女神主動推送她的狀態給“備胎們”,這樣他們就可以去做其他事情了!
public class App {
public static void main(String[] args) throws Exception{
Beauty beauty = new Beauty();
LittleBoy littleBoy = new LittleBoy();
// 添加女神微信
beauty.littleBoy = littleBoy;
// 發佈動態
beauty.publishWechat();
}
}
嗯!這樣一來就智能多了! 女神更新朋友圈後主動推送消息給備胎!備胎不用死守着女神的朋友圈,而是收到消息後自動去查看。所以他們的關係是這樣了:
但是,現在又有一個新問題!這段代碼好像顯得不夠面向對象
,不夠專業。
- 女神如果想要新加一個舔狗,就要動女神的邏輯代碼。
- 新加了一個備胎之後,不知道如何把自己的動態分享給他(例如上面的active方法,可能“新備胎”沒有)。
- 備胎突然舔不動了怎麼辦了,他不想再收到女神動態了!
既然這樣,我們把這段代碼修改下,讓它變得“靈活”,更加“面向對象”些!
V3.0
既然要靈活,面向對象。我們這麼處理:將女神抽象爲一個接口,並且她要能夠刪除備胎,添加備胎,通知備胎。同時我們將備胎抽象爲一個接口,他能夠在收到女神通知後及時做出反應!
Beauty:
LittleBoy:
它們分別有一個實現:BeautyImpl
和LittleBoyImpl
:
測試代碼:
public class App {
public static void main(String[] args) {
Beauty beauty = new BeautyImpl();
LittleBoy boy1 = new LittleBoyImpl("小豪");
LittleBoy boy2 = new LittleBoyImpl("小吳");
// 添加兩個備胎
beauty.addLittleBoy(boy1);
beauty.addLittleBoy(boy2);
// 發佈朋友圈
beauty.publishWechat("最美的不是下雨天,是曾和你一起躲過雨的屋檐!");
// 刪除備胎1,並且新添加了備胎3
beauty.removeLittleBoy(boy1);
beauty.addLittleBoy(msg -> {
System.out.println(" 小李:哎喲,不錯哦!");
});
// 再次發佈朋友圈
beauty.publishWechat("哪裏有彩虹告訴我。。。");
}
}
嗯!通過面向接口編程完美的解決了上面的問題,現在女神這個類已經變得非常靈活了,仔細觀察,我們已經把我們上面的說的案例完全實現!現在它們的關係是這樣的:
擴展
觀察者模式這種發佈與訂閱的思想
使用的非常廣泛,基本各個框架,思想都能看到它的身影,而jdk中也已經抽象了觀察與被觀察者:java.util.Observer
表示觀察者:java.util.Obserable
表示被觀察者(例如上面的女神):
然後美中不足的是,jdk把Observable設計成了一個類,這並不利於擴展! 當然我們仍然可以自己實現接口,就像上面所做的。
總結
我們從觀察者模式特點入手,通過一個案例,一步一步完善了觀察着的寫法,特點!組後介紹了jdk總已有的實現!
關注我,這裏只有乾貨!
同系列文章:
從未這麼明白的設計模式(一):單例模式