前言
我建議很多人著急去了解某些框架源碼的人,自己要做好一定的知識(shí)儲(chǔ)備,先把基礎(chǔ)做好,再去解讀人家源碼,否則你只會(huì)盲目的崇拜(因?yàn)槿思覍?xiě)的太好,但你看不懂人家寫(xiě)的東西),然后收藏起來(lái),從而一篇篇好文章被打入你的冷宮。
我們知道前端MVVM框架最核心的內(nèi)容是其響應(yīng)式系統(tǒng)。想要完全解讀整個(gè)響應(yīng)式系統(tǒng),就必須要了解其中涉及的到發(fā)布者與訂閱者設(shè)計(jì)模式。
同樣在Java中,我們一般用該設(shè)計(jì)模式來(lái)實(shí)現(xiàn)消息隊(duì)列。
該文章并不去研究響應(yīng)式系統(tǒng)的實(shí)現(xiàn),也不研究消息隊(duì)列的實(shí)現(xiàn)。只是在語(yǔ)言層面上給剛?cè)肟拥暮⒆觽兊膯⑹纠印?/strong>
什么是 發(fā)布者與訂閱者?
這種設(shè)計(jì)模式,簡(jiǎn)單的說(shuō),例如我們?cè)谖⑿胖嘘P(guān)注過(guò)的訂閱號(hào)。那該訂閱號(hào)我們可以稱(chēng)為發(fā)布者,我們每個(gè)訂閱者(關(guān)注該訂閱號(hào)的微信)可以稱(chēng)為訂閱者。每當(dāng)該訂閱號(hào)發(fā)布消息的時(shí)候,并不是發(fā)送給所有微信用戶,而是會(huì)選擇所有訂閱該訂閱號(hào)的微信用戶。
用代碼來(lái)解釋下,我們需要兩個(gè)角色
-
發(fā)布者
添加訂閱 (我們所謂的關(guān)注其訂閱號(hào))
移除訂閱 (我們?nèi)∠P(guān)注該訂閱號(hào))
通知訂閱者 (訂閱號(hào)發(fā)布消息,所有關(guān)注者都會(huì)收到) -
訂閱者
接收消息 (接收訂閱號(hào)發(fā)布的消息)
訂閱者注冊(cè)

發(fā)布者發(fā)布消息

了解以上關(guān)系后,我們來(lái)用最少的代碼,用JS和JAVA分別來(lái)實(shí)現(xiàn)一下這個(gè)設(shè)計(jì)模式吧。
JavaScript最簡(jiǎn)單實(shí)現(xiàn)
// 微信訂閱號(hào) -- 發(fā)布者
class Dep {
constructor(name) {
// 訂閱號(hào)名字
this.name = name
// 該訂閱號(hào)內(nèi)存的訂閱者
this.subs = []
}
// 添加訂閱者
addSub(sub) {
this.subs.push(sub)
}
// 發(fā)布消息通知所有訂閱者
notifySubs(notifyInfo) {
this.subs.forEach((sub) => {
sub.receiveInfo(notifyInfo)
})
}
}
// 微信號(hào) -- 訂閱者
class Sub {
constructor(name) {
// 微信用戶名字
this.name = name
}
// 接收訂閱號(hào)發(fā)布的消息
receiveInfo(notifyInfo) {
console.log('尊敬的' + this.name + ', ' + notifyInfo)
}
}
// Test
let d1 = new Dep('王者榮耀訂閱號(hào)')
let d2 = new Dep('騰訊棋牌訂閱號(hào)')
let s1 = new Sub('小雪')
let s2 = new Sub('小黑')
let s3 = new Sub('小白')
// 王者榮耀訂閱號(hào)添加訂閱者
d1.addSub(s1)
d1.addSub(s2)
// 騰訊棋牌訂閱號(hào)添加訂閱者
d2.addSub(s2)
d2.addSub(s3)
// 王者榮耀訂閱號(hào)發(fā)布消息
d1.notifySubs('王者榮耀更新了,快來(lái)圍觀??!')
console.log('============')
// 騰訊棋牌訂閱號(hào)發(fā)布消息
d2.notifySubs('騰訊棋牌有新玩法了,快來(lái)圍觀啊!')
以上會(huì)看到 每個(gè)訂閱號(hào)發(fā)布消息后,會(huì)發(fā)給對(duì)應(yīng)的訂閱者。
我相信移除你會(huì)寫(xiě)吧?
Java 的最簡(jiǎn)單實(shí)現(xiàn)
import java.util.ArrayList;
// 微信訂閱號(hào) -- 發(fā)布者
class Dep {
private String name;
private ArrayList<Sub> subs = new ArrayList<Sub>();
public Dep(String name) {
this.name = name;
}
// 添加訂閱者
public void addSub (Sub sub) {
subs.add(sub);
}
// 發(fā)布消息通知所有訂閱者
public void notifySubs (String notifyInfo) {
for (Sub sub : subs) {
sub.receiveInfo(notifyInfo);
}
}
}
// 微信號(hào) -- 訂閱者
class Sub {
private String name;
public Sub (String name) {
this.name = name;
}
// 接收訂閱號(hào)發(fā)布的消息
public void receiveInfo (String notifyInfo) {
System.out.println("尊敬的" + this.name + ", " + notifyInfo);
}
}
public class TestDepAndSub {
public static void main (String[] args) {
Dep d1 = new Dep("王者榮耀訂閱號(hào)");
Dep d2 = new Dep("騰訊棋牌訂閱號(hào)");
Sub s1 = new Sub("小雪");
Sub s2 = new Sub("小黑");
Sub s3 = new Sub("小白");
// 王者榮耀訂閱號(hào)添加訂閱者
d1.addSub(s1);
d1.addSub(s2);
// 騰訊棋牌訂閱號(hào)添加訂閱者
d2.addSub(s2);
d2.addSub(s3);
// 王者榮耀訂閱號(hào)發(fā)布消息
d1.notifySubs("王者榮耀更新了,快來(lái)圍觀??!");
System.out.println("============");
// 騰訊棋牌訂閱號(hào)發(fā)布消息
d2.notifySubs("騰訊棋牌有新玩法了,快來(lái)圍觀??!");
}
}
同樣我們也得到了相應(yīng)的結(jié)果。

總結(jié)
框架源碼肯定要看的,但我們不要忘了,我們?yōu)槭裁慈タ丛创a,不是為了跟風(fēng)看而看,也不要越過(guò)自己的技術(shù)底線去看,腳踏實(shí)地一步一步來(lái),掌握好每一個(gè)基礎(chǔ)知識(shí)點(diǎn),再去閱讀源碼吧,你會(huì)事半功倍的。
初學(xué)者可以關(guān)注下,以后會(huì)更新適合初學(xué)者的入門(mén)文章,循序頓進(jìn)講解下Vue的運(yùn)行機(jī)制和原理。