发布订阅模式和观察者模式很像,他们的主要区别就是发布订阅模式在中间加了一层,完成对订阅者的通知
Broker.js(中间层)
class Broker {
constructor() {
// 存储订阅的频道和订阅者
this.infoMap = new Map();
}
// topic为订阅的主题
getSubscriber(topic) {
return this.infoMap.get(topic) || [];
}
subscribe(topic, sub) {
const subscribers = this.getSubscriber(topic);
subscribers.push(sub);
this.infoMap.set(topic, subscribers);
}
unsubscribe(topic, sub) {
const subscribers = this.getSubscriber(topic);
const index = subscribers.indexOf(sub);
if (index > -1) {
subscribers.splice(index, 1);
}
this.infoMap.set(topic, subscriber);
}
notifySubscribers(topic, msg) {
const subscribers = this.getSubscriber(topic);
subscribers.forEach((sub) => {
sub.getMsg(topic, msg);
});
}
}
Publisher.js (发布者)
class Publisher {
constructor(broker) {
this.broker = broker;
}
publish(topic, msg) {
console.log(`${topic}已经发布了新内容----${msg}`);
this.broker.notifySubscribers(topic, msg);
}
}
Subscriber.js
class Subscriber {
constructor(broker) {
this.broker = broker;
}
subscribe(topic) {
console.log("订阅成功");
// 通过中间层对发布者进行订阅
this.broker.subscribe(topic, this);
}
unsubscribe(topic) {
console.log("取消订阅成功");
// 通过中间层取消对发布者的订阅
this.broker.unsubscribe(topic, this);
}
getMsg(topic, msg) {
console.log(`${topic}主题更新了--${msg}`);
}
}
使用`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script src="./Broker.js"></script>
<script src="./Publisher.js"></script>
<script src="./Subscriber.js"></script>
<script>
const broker = new Broker();
const sub1 = new Subscriber(broker);
const sub2 = new Subscriber(broker);
const pub = new Publisher(broker);
sub1.subscribe("恐怖片");
sub2.subscribe("恐怖片");
pub.publish("恐怖片", "恐怖片更新了");
</script>
</body>
</html>