從下圖中可以看出,觀察者模式中觀察者和目標(biāo)直接進(jìn)行交互,而發(fā)布訂閱模式中統(tǒng)一由調(diào)度中心進(jìn)行處理,訂閱者和發(fā)布者互不干擾。這樣一方面實(shí)現(xiàn)了解耦,還有就是可以實(shí)現(xiàn)更細(xì)粒度的一些控制。比如發(fā)布者發(fā)布了很多消息,但是不想所有的訂閱者都接收到,就可以在調(diào)度中心做一些處理,類似于權(quán)限控制之類的。還可以做一些節(jié)流操作。
二 概念上的區(qū)別
1.觀察者模式,目標(biāo)和觀察者是基類,目標(biāo)提供維護(hù)觀察者的一系列方法,觀察者提供更新接口。具體觀察者和具體目標(biāo)繼承各自的基類,然后具體觀察者把自己注冊到具體目標(biāo)里,在具體目標(biāo)發(fā)生變化時(shí)候,調(diào)度觀察者的更新方法。
比如有個(gè)“天氣中心”的具體目標(biāo)A,專門監(jiān)聽天氣變化,而有個(gè)顯示天氣的界面的觀察者B,B就把自己注冊到A里,當(dāng)A觸發(fā)天氣變化,就調(diào)度B的更新方法,并帶上自己的上下文。
2.發(fā)布訂閱,訂閱者把自己想訂閱的事件注冊到調(diào)度中心,當(dāng)該事件觸發(fā)時(shí)候,發(fā)布者發(fā)布該事件到調(diào)度中心(順帶上下文),由調(diào)度中心統(tǒng)一調(diào)度訂閱者注冊到調(diào)度中心的處理代碼。
比如有個(gè)界面是實(shí)時(shí)顯示天氣,它就訂閱天氣事件(注冊到調(diào)度中心,包括處理程序),當(dāng)天氣變化時(shí)(定時(shí)獲取數(shù)據(jù)),就作為發(fā)布者發(fā)布天氣信息到調(diào)度中心,調(diào)度中心就調(diào)度訂閱者的天氣處理程序。
三、發(fā)布訂閱模式簡介
1)定義和原理
發(fā)布訂閱模式是一種消息傳遞模式,其中發(fā)布者發(fā)布消息,而訂閱者接收和處理這些消息。它是一種松耦合的通信方式,允許發(fā)布者和訂閱者在不知道彼此存在的情況下進(jìn)行通信。
發(fā)布訂閱模式的原理基于消息隊(duì)列或主題,發(fā)布者將消息發(fā)布到特定的消息隊(duì)列或主題中,而訂閱者可以訂閱這些消息隊(duì)列或主題以接收和處理消息。發(fā)布者和訂閱者之間的通信是異步的,這意味著發(fā)布者發(fā)布消息后,訂閱者可以在任何時(shí)候接收和處理消息。
發(fā)布訂閱模式的核心思想是將發(fā)布者和訂閱者解耦,使得它們可以獨(dú)立地運(yùn)行和擴(kuò)展。這種解耦有助于提高系統(tǒng)的靈活性和可伸縮性,因?yàn)榘l(fā)布者和訂閱者可以根據(jù)需要進(jìn)行擴(kuò)展和修改,而不會(huì)影響彼此的操作。
發(fā)布訂閱模式在許多領(lǐng)域都有應(yīng)用,如
- 消息隊(duì)列
- 事件驅(qū)動(dòng)架構(gòu)
- 實(shí)時(shí)數(shù)據(jù)更新
- 消息推送
它是一種非常有用的通信模式,可以幫助開發(fā)人員構(gòu)建高效、可靠和可擴(kuò)展的系統(tǒng)。
2) 發(fā)布訂閱模式的優(yōu)勢
發(fā)布訂閱模式具有以下優(yōu)勢:
- 解耦:發(fā)布者和訂閱者是松耦合的,它們可以獨(dú)立地運(yùn)行和擴(kuò)展,而不會(huì)相互影響。
- 靈活性:發(fā)布者可以隨時(shí)發(fā)布消息,而訂閱者可以隨時(shí)訂閱和取消訂閱消息,這使得系統(tǒng)更加靈活。
- 可伸縮性:發(fā)布者和訂閱者可以根據(jù)需要進(jìn)行擴(kuò)展和修改,而不會(huì)影響彼此的操作。
- 異步通信:發(fā)布者和訂閱者之間的通信是異步的,這意味著發(fā)布者發(fā)布消息后,訂閱者可以在任何時(shí)候接收和處理消息。
- 消息過濾:訂閱者可以根據(jù)自己的需求訂閱特定的消息,從而實(shí)現(xiàn)消息過濾。
- 可靠性:發(fā)布訂閱模式通常使用消息隊(duì)列或主題來存儲(chǔ)消息,這可以確保消息不會(huì)丟失,并且可以在訂閱者不可用時(shí)進(jìn)行存儲(chǔ)。
- 分布式系統(tǒng):發(fā)布訂閱模式可以在分布式系統(tǒng)中使用,從而實(shí)現(xiàn)跨節(jié)點(diǎn)的通信。
?
四、發(fā)布訂閱模式的實(shí)現(xiàn)
1)消息隊(duì)列
發(fā)布訂閱模式可以使用消息隊(duì)列來實(shí)現(xiàn)。消息隊(duì)列是一種存儲(chǔ)和轉(zhuǎn)發(fā)消息的技術(shù),它可以在發(fā)布者和訂閱者之間提供異步通信。
在發(fā)布訂閱模式中,發(fā)布者將消息發(fā)布到消息隊(duì)列中,而訂閱者可以從消息隊(duì)列中接收和處理消息。消息隊(duì)列可以作為發(fā)布者和訂閱者之間的中間件,它可以確保消息的可靠性和有序性。
使用消息隊(duì)列實(shí)現(xiàn)發(fā)布訂閱模式的步驟如下:
- 創(chuàng)建消息隊(duì)列:創(chuàng)建一個(gè)消息隊(duì)列來存儲(chǔ)和轉(zhuǎn)發(fā)消息。
- 發(fā)布消息:發(fā)布者將消息發(fā)布到消息隊(duì)列中。
- 訂閱消息:訂閱者訂閱消息隊(duì)列以接收和處理消息。
- 處理消息:訂閱者從消息隊(duì)列中接收消息并進(jìn)行處理。
在實(shí)現(xiàn)發(fā)布訂閱模式時(shí),需要考慮以下幾個(gè)方面:
- 消息隊(duì)列的選擇:根據(jù)需求選擇合適的消息隊(duì)列,如 RabbitMQ、Kafka 等。
- 消息的格式:定義消息的格式,以便發(fā)布者和訂閱者能夠理解和處理消息。
- 消息的發(fā)布和訂閱:確定發(fā)布者和訂閱者如何發(fā)布和訂閱消息。
- 消息的處理:訂閱者需要根據(jù)自己的需求處理消息,如數(shù)據(jù)處理、日志記錄等。
- 消息的可靠性:考慮如何確保消息的可靠性,如消息確認(rèn)、消息重試等。
- 消息的有序性:考慮如何確保消息的有序性,如消息排序、消息分組等。
總之,使用消息隊(duì)列實(shí)現(xiàn)發(fā)布訂閱模式可以提供高效、可靠和可擴(kuò)展的通信方式。在實(shí)現(xiàn)時(shí),需要根據(jù)具體需求進(jìn)行選擇和配置。
2)發(fā)布訂閱者
在發(fā)布訂閱模式中,發(fā)布者和訂閱者是兩個(gè)獨(dú)立的實(shí)體,它們通過某種通信渠道(如消息隊(duì)列)進(jìn)行交互。
發(fā)布者負(fù)責(zé)將消息發(fā)布到通信渠道中,而訂閱者則負(fù)責(zé)從通信渠道中接收和處理消息。發(fā)布者和訂閱者之間的通信是異步的,這意味著發(fā)布者發(fā)布消息后,訂閱者可以在任何時(shí)候接收和處理消息。
以下是使用發(fā)布訂閱模式實(shí)現(xiàn)發(fā)布者和訂閱者的基本步驟:
- 創(chuàng)建通信渠道:創(chuàng)建一個(gè)消息隊(duì)列或主題來存儲(chǔ)和轉(zhuǎn)發(fā)消息。
- 發(fā)布消息:發(fā)布者將消息發(fā)布到通信渠道中。
- 訂閱消息:訂閱者訂閱通信渠道以接收和處理消息。
- 處理消息:訂閱者從通信渠道中接收消息并進(jìn)行處理。
在實(shí)現(xiàn)發(fā)布訂閱模式時(shí),需要考慮以下幾個(gè)方面:
- 通信渠道的選擇:根據(jù)需求選擇合適的通信渠道,如消息隊(duì)列、主題等。
- 消息的格式:定義消息的格式,以便發(fā)布者和訂閱者能夠理解和處理消息。
- 消息的發(fā)布和訂閱:確定發(fā)布者和訂閱者如何發(fā)布和訂閱消息。
- 消息的處理:訂閱者需要根據(jù)自己的需求處理消息,如數(shù)據(jù)處理、日志記錄等。
- 消息的可靠性:考慮如何確保消息的可靠性,如消息確認(rèn)、消息重試等。
- 消息的有序性:考慮如何確保消息的有序性,如消息排序、消息分組等。
- 總之,發(fā)布訂閱模式實(shí)現(xiàn)發(fā)布者和訂閱者之間的通信,提供了一種高效、可靠和可擴(kuò)展的通信方式。在實(shí)現(xiàn)時(shí),需要根據(jù)具體需求進(jìn)行選擇和配置。
3)消息主題
在發(fā)布訂閱模式中,消息主題是用于發(fā)布和訂閱消息的標(biāo)識符。它是發(fā)布者和訂閱者之間的橋梁,用于定義訂閱者感興趣的消息類型。
以下是使用消息主題實(shí)現(xiàn)發(fā)布訂閱模式的基本步驟:
- 創(chuàng)建消息主題:創(chuàng)建一個(gè)唯一的消息主題來標(biāo)識要發(fā)布的消息類型。
- 發(fā)布消息:發(fā)布者將消息發(fā)布到特定的消息主題中。
- 訂閱消息:訂閱者訂閱特定的消息主題以接收和處理消息。
- 處理消息:訂閱者從訂閱的消息主題中接收消息并進(jìn)行處理。
在實(shí)現(xiàn)發(fā)布訂閱模式時(shí),需要考慮以下幾個(gè)方面:
- 消息主題的設(shè)計(jì):設(shè)計(jì)合適的消息主題,以便發(fā)布者和訂閱者能夠理解和處理消息。
- 消息的發(fā)布和訂閱:確定發(fā)布者和訂閱者如何發(fā)布和訂閱消息主題。
- 消息的處理:訂閱者需要根據(jù)自己的需求處理消息,如數(shù)據(jù)處理、日志記錄等。
- 消息的可靠性:考慮如何確保消息的可靠性,如消息確認(rèn)、消息重試等。
- 消息的有序性:考慮如何確保消息的有序性,如消息排序、消息分組等。
總之,消息主題是發(fā)布訂閱模式中的重要概念,用于定義發(fā)布者和訂閱者之間的通信。在實(shí)現(xiàn)時(shí),需要根據(jù)具體需求進(jìn)行選擇和配置。
五、發(fā)布訂閱模式的
- 應(yīng)用場景
- 實(shí)時(shí)數(shù)據(jù)更新
- 消息推送
- 事件驅(qū)動(dòng)架構(gòu)
- 注意事項(xiàng)
- 消息丟失和重復(fù)
- 消息順序問題
- 消息過期問題
六 總結(jié)
1. 最大的區(qū)別是調(diào)度的地方。
雖然兩種模式都存在訂閱者和發(fā)布者(具體觀察者可認(rèn)為是訂閱者、具體目標(biāo)可認(rèn)為是發(fā)布者),但是觀察者模式是由具體目標(biāo)調(diào)度的,而發(fā)布/訂閱模式是統(tǒng)一由調(diào)度中心調(diào)的,所以觀察者模式的訂閱者與發(fā)布者之間是存在依賴的,而發(fā)布/訂閱模式則不會(huì)。2. 兩種模式都可以用于松散耦合,改進(jìn)代碼管理和潛在的復(fù)用。
七,?代碼如下
觀察者模式文章來源:http://www.zghlxwxcb.cn/news/detail-836298.html
// 觀察者
class Observer {
constructor() {
}
update(val) {
}
}
// 觀察者列表
class ObserverList {
constructor() {
this.observerList = []
}
add(observer) {
return this.observerList.push(observer);
}
remove(observer) {
this.observerList = this.observerList.filter(ob => ob !== observer);
}
count() {
return this.observerList.length;
}
get(index) {
return this.observerList(index);
}
}
// 目標(biāo)
class Subject {
constructor() {
this.observers = new ObserverList();
}
addObserver(observer) {
this.observers.add(observer);
}
removeObserver(observer) {
this.observers.remove(observer);
}
notify(...args) {
let obCount = this.observers.count();
for (let index = 0; index < obCount; index++) {
this.observers.get(i).update(...args);
}
}
}
?發(fā)布/訂閱模式文章來源地址http://www.zghlxwxcb.cn/news/detail-836298.html
class PubSub {
constructor() {
this.subscribers = {}
}
subscribe(type, fn) {
if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {
this.subscribers[type] = [];
}
this.subscribers[type].push(fn);
}
unsubscribe(type, fn) {
let listeners = this.subscribers[type];
if (!listeners || !listeners.length) return;
this.subscribers[type] = listeners.filter(v => v !== fn);
}
publish(type, ...args) {
let listeners = this.subscribers[type];
if (!listeners || !listeners.length) return;
listeners.forEach(fn => fn(...args));
}
}
let ob = new PubSub();
ob.subscribe('add', (val) => console.log(val));
ob.publish('add', 1);
到了這里,關(guān)于觀察者模式和發(fā)布訂閱模式的區(qū)別的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!