來到心儀已久的公司面試,剛推開門還沒等我說話HR 小姐姐就主動問我:你是來參加面試的吧?
我心想不對啊:難道是因為我長的帥,小姐姐一眼就看出來我將來是這棟樓的主人,所以才主動跟我打招呼。
我昂起頭,略微點點頭:是的。
HR小姐姐:面試官馬上就過來,我先帶你去會議室。
在去會議室的路上,我發現大家脖子上都帶著亮閃閃的工牌,我下意識的看了看我的脖子上,除了昨天沒有洗澡留下來的一點汗漬啥也沒有。
原來是因為我沒帶工牌才認出我的,頓時我的臉滾燙滾燙的,我承認剛才我有點自戀了。
HR小姐姐:怎麼了,你臉怎麼紅通通的,是不舒服嗎?
我摸了摸臉:沒有沒有,面試有點緊張,害。
來到會議室,HR 小姐姐給我遞過一杯水:面試官臨時有個會,你稍微等一會。
我:好的。
我心裡咕嚕:怎麼突然有個會,會不會是因為看了我的簡歷覺得我菜,故意找了一個藉口,待會肯定讓 HR 過來說面試太忙今天不面了。
果不其然,門開了,一位頭髮油油的滿臉是痘的中年大叔向我走來。
我心想:這不會就是傳說中的架構師吧。看來還是很看重我啊,第一面就派一個架構師來面我,我得好好表現一下。
架構師:你就是xxx 吧,剛才有個會議我來晚了,我們開始面試吧,一分鐘簡單介紹一下自己。
果然沒有猜錯,給我一分鐘介紹,幸虧之前是按照一分鐘準備的,我要開始背了。
我張嘴一笑,露出自信的大牙:尊敬的架構師你好,我是 xxx,之前在上一家公司擔任……
架構師點點頭:很好。我看你簡歷上寫了很多技能,你挑一個你最熟悉的。
我有點凌亂了:架構師怎麼不按套路出牌,應該會問我 HashMap 的原始碼,Java 鎖的機制等。我想了想我比較熟悉的:Java 集合類、JVM、多執行緒、spring 全家桶,我如果說這些肯定會被架構師鄙視,差點忘了我還有一個殺手鐧:設計模式。
我拍了拍胸脯:架構師你好,我之前參與專案重構用到了很多設計模式,要不你問我設計模式的東西吧。
架構師:那你說說觀察者模式和釋出訂閱模式的區別?
我腦海立刻閃現《Head First設計模式》裡面講的:Publishers + Subscribers = Observer Pattern,問這麼簡單的問題難道是看不起我嗎。
我內心無比激動,嘴角露出勝利者的微笑:親愛的架構師,我之前看過一本書《Head First 設計模式》,這裡面講的觀察者模式和釋出訂閱模式是等同關係的,它們是一回事。
架構師也笑了:不,它們不一樣。
此刻我慌了,雙手有點輕微顫抖,我哪裡錯了,它們明明是相等的。
架構師:我待會還有個會,要不今天的面試先到這裡,你回家等訊息吧。
回家後我心不甘,決定要把觀察者模式和釋出訂閱模式搞清楚,透過一頓谷歌後我寫了下面這些筆記:
觀察者模式觀察者模式一般有觀察者和被觀察者。舉個例子:大家在學校上自習的時候,等老師走了有些人會玩手機、吃零食、交頭接耳找隔壁妹妹聊天,但是被老師發現可就不好了,所以大家想了一個招,讓坐在最後排的同學幫忙“放風”,老師一來就給大家一個手勢通知大家,大家就繼續裝好好學生(哈嘿)。
這其實就是一個典型的觀察者模式,“放風”的同學是被觀察者,玩手機、吃零食的同學是觀察者,大家都在觀察“放風”同學的手勢,一旦老師來了,被觀察者就會通知大家。
好了,讓我們看看 UML 建模是如何定義的。
觀察者模式定義物件間一種一對多的依賴關係,使得每當一個物件改變狀態,則所有依賴於它的物件都會得到通知並自動更新。
UML結構圖如下:
Observer類是抽象觀察者,為所有的具體觀察者定義一個介面,在得到主題的通知時更新自己。
ConcreteSubject類是具體主題,將有關狀態存入具體觀察者物件,在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
ConcreteObserver是具體觀察者,實現抽象觀察者角色所要求的更新介面,以便使本身的狀態與主題的狀態相協同。
釋出訂閱模式舉個生活中的例子,比如我們想要訂閱一份國家地理雜誌,一般需要我們先向郵局申請(付錢),告訴郵局我要訂閱這份雜誌,苦等數日雜誌終於印刷好了,這個時候我們不會直接跑到印刷廠裡去,而是等印刷廠將雜誌送給郵局,然後郵局才會慢吞吞地將雜誌送到家(推模式),如果你實在等不及了跑到郵局直接取雜誌,恭喜你學會了“拉模式”。
用專業術語來解釋釋出訂閱模式:
訂閱者把自己想訂閱的事件註冊到排程中心,當該事件觸發時候,釋出者釋出該事件到排程中心(順帶上下文),由排程中心統一排程訂閱者註冊到排程中心的處理程式碼。
在釋出訂閱模式裡釋出者並不會直接通知訂閱者,換句話說釋出者和訂閱者彼此互不感知。
那釋出者和訂閱者如何交流呢?答案是透過中間的排程中心。
釋出者將訊息傳送給排程中心,告訴它你幫我把訊息放到 Topic1中。訂閱者告訴排程中心,我需要訂閱 topic1,你幫我留意一下。當有訊息來了,訂閱者可以採取拉模式或者推模式來獲取訊息。有態度的總結話不多說,先上一張圖:
從表面上看:
觀察者模式裡只有兩個角色:觀察者和被觀察者。釋出訂閱模式裡有三種角色:釋出者、訂閱者、排程器(第三者)。往更深層次講:
觀察者和被觀察者是松耦合的關係。釋出者和訂閱者則完全不存在耦合。從使用層面上講:
觀察者模式經常用於單個應用內部。釋出訂閱模式更多是一種跨應用的模式(cross-application pattern),比如我們常用的訊息中介軟體Kafka 等。綜上:觀察者模式和釋出訂閱模式本質上都有釋出訂閱的思想,但是又有一定的區別,所以我們不能將二者完全等同起來。