最近想深刻研究下響應式編程,做爲基礎頗有必要來把觀察者模式擼一遍;一開始我是以爲很easy,而後就直接開擼了,擼着擼着發現擼不動了。由於我忽然不太明白這個模式了,說好的觀察者,到底發佈-訂閱的二者執行者誰纔是觀察者?又或者說還有其餘角色?可是根據《JAVA與模式》一書中的結構,並無額外的角色出現。
java
思考中....,好吧想不出來....,跑步去...編程
跑步時我給本身羅列了幾個問題:後端
這裏先拋出定義:GOF給觀察者模式以下定義:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。設計模式
這裏因爲一些定式思惟,總會以爲既然是「被觀察者」,那麼這個「被」字就是否是就代表「被觀察者」是被動接受變動的一方,也就是接受通知的一方呢?微信
以前我也是走到這個衚衕裏了,程序寫完總以爲哪裏不對;回過頭看,仍是本身太年輕,沒有get到哪些大佬們的點。app
先來看程序;這裏用掘金來打個比方,個人博客glmmaper做爲被觀察者,也就是發佈者。掘金小夥伴們做爲觀察者,也就是訂閱者。ide
具體邏輯:小夥伴們(訂閱者)關注(訂閱)了個人博客(發佈者),若是我發佈了一篇文章(狀態變動),就會通知(推送消息)全部關注個人小夥伴。spa
package com.glmapper.designmode.observor;
/** * @description: 抽象主題接口 * @email: <a href="glmapper_2018@163.com"></a> * @author: 磊叔 * @date: 18/4/22 */
public interface Subject {
/** * 新增關注者 * @param observer 關注的小夥伴 */
void addFocusObserver(Observer observer);
/** * 取消關注 * @param observer 取消關注的小夥伴 */
void removeFocusObserver(Observer observer);
/** * 通知機制,通知機制由相關事件來觸發,好比說發佈文章 * @param blogName 博客名 * @param articleName 文章名 */
void notifyObservers(String blogName,String articleName);
}
複製代碼
三個方法,一個是博客主頁增長了一個關注者;一個是博客主頁有小夥伴取消的關注(對於博客來講就是移除一個關注者,這裏不知道是否也會以爲彆扭?明明你取消的關注,爲啥說成是我移除你,也就是不讓你關注了,還能這麼玩?這裏確定是須要在引入其餘的一些輔助機制,好比說你在客戶端發起了一個取消關注的請求,後端處理的時候掘金的工程師們就是在個人關注列表中將你移除的,嗯,這麼一想確實是我不讓你關注了。😄....);最後一個方法是發起一個通知。下面是一個具體的博客,好比說是glmapper;設計
package com.glmapper.designmode.observor;
import java.util.ArrayList;
import java.util.List;
/** * @description: 這個是具體發佈者,這裏比喻成個人博客glmapper * @email: <a href="glmapper_2018@163.com"></a> * @author: 磊叔 * @date: 18/4/22 */
public class ConcreteSubject implements Subject {
/** 個人當前關注列表 */
List<Observer> Observers = new ArrayList<>();
/** 個人博客名 :求關注 */
private static final String blogName = "glmapper";
@Override
public void addFocusObserver(Observer observer) {
Observers.add(observer);
}
@Override
public void removeFocusObserver(Observer observer) {
Observers.remove(observer);
}
@Override
public void notifyObservers(String blogName,String articleName) {
for (Observer observer:Observers) {
observer.update(blogName,articleName);
}
}
/** * 這裏是發佈文章,觸發通知事件 */
public void publishArticle(String articleName){
notifyObservers(blogName,articleName);
}
}
複製代碼
前面提到,通知事件確定是因爲某些狀態發生變動了,纔會進行通知,這裏就能夠比方爲我發佈了一篇博客,而後通知你(這裏只能假如你關注了)。再來看觀察者:code
package com.glmapper.designmode.observor;
/** * @description: 訂閱者抽象接口 * @email: <a href="glmapper_2018@163.com"></a> * @author: 磊叔 * @date: 18/4/22 */
public interface Observer {
/** * 調用此方法會更新狀態,作出相應的動做 * @param blogName * @param articleName */
void update(String blogName,String articleName);
}
複製代碼
抽象訂閱者,有一個update方法,通知你去作出相應的動做,具體動做每一個觀察者均可能不一樣。
package com.glmapper.designmode.observor;
/** * @description: 這個是具體訂閱者,這裏能夠比喻成博客關注者, * 收到變動信息以後須要作出相應的動做 * @email: <a href="glmapper_2018@163.com"></a> * @author: 磊叔 * @date: 18/4/22 */
public class ConcreteObserver implements Observer {
@Override
public void update(String blogName,String articleName) {
System.out.println(blogName+"發佈了新的文章,文章名爲:"+articleName);
read(articleName);
}
private void read(String articleName){
System.out.println("即將閱讀 "+articleName+" 這篇文章");
}
}
複製代碼
上面是一個具體的關注者,加入說就是你。博客更新以後發了一個通知給你(掘金app推送的消息),而後你點了一下,這個也是一種動做。例子中舉的是read,就是關注者作出閱讀的動做。
看下最後的運行結果:
package com.glmapper.designmode.observor;
/** * @description: [描述文本] * @email: <a href="glmapper_2018@163.com"></a> * @author: 磊叔 * @date: 18/4/22 */
public class MyMainIndex{
public static void main(String[] args) {
//博客主體
ConcreteSubject subject = new ConcreteSubject();
//關注者:handSome是帥氣的意思
Observer handSome = new ConcreteObserver();
//增長一個關注者
subject.addFocusObserver(handSome);
//發一篇文章
subject.publishArticle("設計模式-觀察者模式");
}
}
glmapper發佈了新的文章,文章名爲:設計模式-觀察者模式
即將閱讀 設計模式-觀察者模式 這篇文章
複製代碼
酒桶說:啊,歡樂時光老是短暫的
因此做爲積累,仍是須要將一些基本的概念來羅列一下的。
主要角色:
具體關係:
抽象主題(Subject)(接口)-->被具體主題(ConcreteSubject)角色(1個)實現
抽象觀察者(Observer)(接口)-->被具體觀察者(ConcretedObserver)角色(N個)實現
觀察者對象載入主題方法,並在主題方法中調用觀察者對象實現的接口方法update來讓本身發生變動響應。
一些場景:
基於發佈訂閱的具體實現例子仍是不少的,比較典型的就是這種訂閱一個博客,而後博客更新推送;還有微信公衆號,服務號這些。
到這裏咱們再回過頭來看一開始留下的幾個問題:
OK,觀察者模式就擼到這裏,也歡迎小夥伴們提出本身珍貴的意見;有寫的不當之處煩請及時提出。
播報:菜鳥成長系列又開始更新了....