首先, 提到观察者模式, 这不禁让我想到了 MVVM,MVVM 架构模式感觉用到了观察者的思想.
我们还是按照惯例, 了解一下什么是观察者模式
观察者模式, 类似发布订阅模式, 完成这个动作首先最少得有两个不同的对象, 或者多个对象, 他更像是一种一队多的依赖关系, 也就是一种对象的状态发生改变, 与其相关所有的对象的状态都会发生改变; 比如说朋友圈这个功能, 一个人可能有上百个好友, 当我发布一条朋友圈后, 所有和我成为好友的人都会看见这个朋友圈, 当另一个人点赞后, 所有你的好友其他点赞的人也会收到通知, 这很像观察者, 也就是我是发布者, 我的好友是订阅者.
然后我们看一下什么是 vue,vue 的原理大家都知道, 他是一种自底向上的一种深入响应式的双向绑定模式, 即 MVVM, 也就是说, vue 关注 model 的变化, model 的变化让 mvvm 框架更新 dom, 从而产生视图 view 变化.
举一个项目中很常见的例子:
在写 vue 项目中我们都用过父子组件传值, 但是兄弟组件传值是怎么实现的, 首先我们可以用 vuex, 这很常见, 但是还有一种方法不知道你用过没有, 就是 Bus, 这个 Bus 只是一种命名而已, 叫什么无所谓, 你可以叫飞机大炮都可以, 这不重要, 我们主要看看他是怎么实现的:
第一步, 我们先在 main.JS 中注册一下 bus:
Vue.prototype.$Bus = new Vue()
我们往 vue 的原型里注册了一个全局变量 $Bus, 他的值是 vue 的实例, 也就是说, 到现在为止,$Bus 里边有了 vue 所有的属性和方法, 这下就好操作了
第二步, 我们开始发送消息, 这就很符合观察者模式的发布订阅模式
我们在组件 1 中写如下代码:
- <template>
- <div>
- <button @click="send"> 发送 </button>
- </div>
- </template>
- <script>
- export default {
- methods: {
- send () {
- this.$Bus.$emit("send",'接收的信息')
- }
- }
- }
- </script>
点击按钮发送一条信息, 这个按钮也就是充当发布者, 我们用到了 vue 的 $emit 这个 API, 那么订阅者是什么呢? 我不说你也应该想到了, 对, 就是他
第三步, 在组件三中接收消息
<template> <div> {{message}} </div> </template> <script> export default { data () { return { message: '' } }, mounted () { this.$Bus.$on('send', (msg) => { this.message = msg }) } } </script>
就是用 $on 这个属性充当接收者
从上可以看出, vue 很多地方用到了观察者的思想, 包括他的双向绑定也是如此, 首先我们看看 vue 的机制:
从上图我们可以看出, vue 是通过 Object.defineProperty 实现对数据的劫持, 然后中间做了一个中转, 最后渲染到 vue 层.
我们可以肯定的是, vue.js 借鉴了观察者模式, 但是我感觉还是有点区别的, 观察者模式跟注重的是事件驱动, 比如我买房这个动作, 第一次和销售了解可能没有合适的房源, 然后销售就会跟你说: '如果有合适的房源我们会第一时间通知你', 当有新房源的时候他会给你打电话通知你, 这一系列的根源是买房这个事件, 他驱动了整套流程. 而 vue 我们都知道是数据驱动, 也就是只有 data 里的值发生改变的话, Object.defineProperty 才会对他劫持, 从而去更新 dom, 触发视图的更新.
那么有没有更符合观察者模式特征的?
当然是 node.JS 的 events 事件了.
首先我们看看 events 的工作流程:
var events = require('events'); // 创建 eventEmitter 对象 var eventEmitter = new events.EventEmitter(); // 创建事件处理程序 var connectHandler = function connected() { console.log('连接成功.'); // 触发 data_received 事件 eventEmitter.emit('data_received'); } // 绑定 connection 事件处理程序 eventEmitter.on('connection', connectHandler); // 使用匿名函数绑定 data_received 事件 eventEmitter.on('data_received', function(){ console.log('数据接收成功.'); }); // 触发 connection 事件 eventEmitter.emit('connection'); console.log("程序执行完毕.");
输出一下:
这就完全符合观察者的工作模式, 由 emit 发布, 由 on 接收. 所以说, node.JS 提供了很好的监听机制, 还有他对整个事务的处理 . 其支持了 Node.JS 最特色的 I/O 模式, 比如我们启动 http 服务时会监听其 connect / close,http.request 时会监听 data / end 等.
还有没有类似的案例呢?
当然, JS 有一个事件监听者 ----addEventListener, 也有点观察者的意思, 具体用法我就不说了, 想必大家用的都很熟悉.
其实只要你认真想一想, 还是有很多地方有观察者的身影的, 最简单的就是一个点击事件, 是不是也有其意思, 发布者是一个按钮, 而接收者可以是表单, 弹层等任何东西.
那么, 对于观察者模式存在的意义有哪些呢?
首先我们说说他的优点:
1, 观察者模式需要在观察者和被观察者之间建立一个耦合, 他需要一个更加抽象化将二者联系在一起
2, 观察者模式支持广播, 也就是一对多的关系, 这就让我们很容易想到一个技术, 就是 socket, 具体可以参考 vue 项目使用 websocket 技术
然鹅, 他也是优缺点的:
1, 创建订阅者本身要消耗一定的时间和内存
2, 当订阅一个消息时, 也许此消息并没有发生, 但这个订阅者会始终存在内存中.
3, 观察者模式弱化了对象之间的联系, 这本是好事情, 但如果过度使用, 对象与对象之间的联系也会被隐藏的很深, 会导致项目的难以跟踪维护和理解.
等会儿, 还有一个模式叫发布订阅模式, 很多人都以为他就是观察者模式 (包括我), 后来我上网查了一下, 发现他们还是有区别的, 我们可以说观察者模式和发布订阅模式很像, 真的很像, 但是本质还是有点区别的, 最根本的就是调度中心不同.
举个例子, 观察者模式更注重是目标和观察者是抽象类, 比如天气预报, 观察者 A 负责监听天气的变化, 而 B 想得知天气的变化需要将自己注册到 A 中, 而天气变化的时候 A 触发天气变化, 调度 B 的接口更新变化.
而发布订阅模式是如何完成这个动作的呢? A 想要感知天气变化, 需要 B 这个调度中心, 而 B 得到天气变化需要依赖 C 的触发, 可能我解释的不是很清楚, 网上有两个图比较好, 我粘到下面, 提供参考 (侵权必删哈哈哈)
好了, 对于观察者模式我的理解就到这里, 欢迎指正!
来源: https://www.cnblogs.com/qisi007/p/11002583.html