观察者模式-订阅发布模式

观察者模式(Observer Pattern)

观察者模式是一种对象间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖他的对象都将得到通知。通常运用在对象之间的消息通讯中。

// 比如现在有一群学生,可以组成小组,可以寻求帮助 class Students { constructor(name, level) { this.name = name; this.level = level; this.tasks = []; } askForHelp(subject) { console.log(`关于${subject}, ${this.level}${this.name}向大家寻求帮助!`) this.tasks.forEach((fn) => { fn(subject); }); } makeTeam(student, fn) { console.log(`${this.level}${this.name}与${student.level}${student.name}组成了学习小组!`); student.tasks.push(fn); } } const studentWango = new Students('Wango', '学神'); const studentLily = new Students('Lily', '学霸'); const studentTom = new Students('Tom', '平平无奇的'); const studentPeter = new Students('Peter', '学渣'); // 老师说Peter的成绩比较差,所以大家都和Peter组成了学习小组 studentWango.makeTeam(studentPeter, function(subject) { console.log(`Wango说:${subject}确实很难,我也花了好几分钟复习才堪堪得到了满分!`); }) // 学神Wango与学渣Peter组成了学习小组! studentLily.makeTeam(studentPeter, function(subject) { console.log(`Lily说:${subject}!? 背就完事了!`); }) // 学霸Lily与学渣Peter组成了学习小组! studentTom.makeTeam(studentPeter, function(subject) { console.log(`Tom说:${subject}的话,一定要好好学,但学不好也没事,我们都是凡人!`); }) // 平平无奇的Tom与学渣Peter组成了学习小组! // 有一天... studentPeter.askForHelp('英语'); // 关于英语, 学渣Peter向大家寻求帮助! // Wango说:英语确实很难,我也花了好几分钟复习才堪堪得到了满分! // Lily说:英语!? 背就完事了! // Tom说:英语的话,一定要好好学,但学不好也没事,我们都是凡人! 发布订阅模式(Pub-Sub Pattern)

发布订阅模并不在24种设计模式之中,只是观察者模式的一种变体。相比观察者模式,订阅发布模式新增了一个任务调度中心,订阅者将自己想要订阅的事件注册到调度中心,当发布者发布该事件到调度中心,也就是触发该事件时,由调度中心同一调度订阅者注册到调度中心的代码。

// 同样的学习小组 class Students { constructor(name, level) { this.name = name; this.level = level; } // 订阅事件 on(type, fn) { ClassRoom.subscribe(type, fn); } // 发布内容 emit(type, content) { ClassRoom.askForHelp(type, content); } } // 任务调度中心 class ClassRoom { static topic = Object.create(null) // 对于某个事件发布任务 static askForHelp(type, content) { console.log(`${type}:${content}`); if (!ClassRoom.topic[type] || ClassRoom.topic[type].length === 0) { console.log(`然而并没有学生对${type}感兴趣!`); return; } ClassRoom.topic[type].forEach((fn) => { fn(content); }); } // 订阅某个类型的事件 static subscribe(type, fn) { if (!ClassRoom.topic[type]) { ClassRoom.topic[type] = []; } console.log(`有学生订阅了${type}.`); ClassRoom.topic[type].push(fn); } } const studentWango = new Students('Wango', '学神'); const studentLily = new Students('Lily', '学霸'); const studentTom = new Students('Tom', '平平无奇的'); const studentPeter = new Students('Peter', '学渣'); studentWango.on('Life', function(type, content) { console.log(`Wango说: 终于有人问生活上的问题了,果然还是做个凡人比较快乐啊!`); }) // 有学生订阅了Life. studentWango.on('English', function(type, content) { console.log(`Wango说:英语确实很难,我也花了好几分钟复习才堪堪得到了满分!`); }) // 有学生订阅了English. studentTom.on('English', function(type, content) { console.log(`Tom说:英语的话,一定要好好学,但学不好也没事,我们都是凡人!`); }) // 有学生订阅了English. studentLily.on('English', function(type, content) { console.log(`Lily说: 英语?! 背就完事了!`); }) // 有学生订阅了English. studentLily.emit('Life', '这个世界有英雄吗?'); // Life:这个世界有英雄吗? // Wango说: 终于有人问生活上的问题了,果然还是做个凡人比较快乐啊! studentTom.emit('English', '单词记不住怎么办啊?'); // English:单词记不住怎么办啊? // Wango说:英语确实很难,我也花了好几分钟复习才堪堪得到了满分! // Tom说:英语的话,一定要好好学,但学不好也没事,我们都是凡人! // Lily说: 英语?! 背就完事了! studentPeter.emit('Game', '学什么?玩游戏啊!'); // Game:学什么?玩游戏啊! // 然而并没有学生对Game感兴趣! 区别与联系

相比观察者模,订阅发布模式中的的订阅者和发布者分离更加彻底。订阅者在订阅的时候只关注事件本身,而不用关心是谁发布的信息;而发布者同样只需要关注发布的内容,不用关心是谁在订阅,如何处理。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpygxj.html