JavaScript之观察者模式

本文介绍观察者模式(发布订阅模式)的基本概念与实现原理,通过一个具体的留言统计案例,展示了如何利用观察者模式分离模块间的耦合,实现事件触发与响应。

观察者模式也叫发布订阅模式!,为了解决主体对象与观察者之间功能的耦合。
定义:定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖对象都会收到通知自动更新。

观察者模式主要分为三个步骤:注册、发布、移除。我们一个一个步骤来实现。
我们定义一个容器,再用闭包包起来,防止污染全局变量,里面存放这些方法,以及要观察的事件。

详细解释看注解

 //防止信息队列暴露而被慕改或影响到其他变量
 var Observer = (function () {
     var _messages = {};
     return {
         //注册信息接口
         regist: function (type, fn) {
             //如果此信息不存在则应该创建一个该消息类型
             if (typeof _messages[type] === 'undefined') {
                 //将动作推入到该信息对应的动作执行队列中
                 _messages[type] = [fn];

             } else {
                 _messages[type].push(fn);
             }
         },
         //发布信息接口
         fire: function (type, args) {
             //如果该小心没有被注册,则返回
             if (!_messages[type])
                 return;
             //定义小心信息
             var events = {
                     type: type, //消息类型
                     args: args || {} //消息携带数据
                 },
                 i = 0, //消息动作循环变量
                 len = _messages[type].length; //消息动作长度
             //遍历消息动作
             for (; i < len; i++) {
                 //依次执行注册的消息对应的动作序列
                 _messages[type][i].call(this, events);
             }
         },
         //移除信息接口
         remove: function (type, fn) {
             //如果消息动作队列存在
             if (_message[type] instanceof Array) {
                 //从最后一个消息动作遍历
                 var i = _message[type].length - 1;
                 for (; i >= 0; i--) {
                     //如果存在该动作在消息动作序列中移除相应动作
                     _messages[type][i] === fn && _messages[type].splice(i, 1);
                 }
             }
         }
     }
 })();

上面就是我们定义好的观察者,当我们想要订阅发布某些实例的时候直接调用即可。
接着我们结合实例来看一下这是怎么使用的,例如我们做一个留言并统计浏览数量的小功能

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div>
        <div>
            用户的数量
            <span id="msg_num">0</span>
        </div>
        <ul id="msg">

        </ul>
        <input type="text" id="user_input" />
        <button id="user_submit">提交</button>

    </div>




    <script>
        //防止信息队列暴露而被慕改或影响到其他变量
        var Observer = (function () {
            var _messages = {};
            return {
                //注册信息接口
                regist: function (type, fn) {
                    //如果此信息不存在则应该创建一个该消息类型
                    if (typeof _messages[type] === 'undefined') {
                        //将动作推入到该信息对应的动作执行队列中
                        _messages[type] = [fn];

                    } else {
                        _messages[type].push(fn);
                    }
                },
                //发布信息接口
                fire: function (type, args) {
                    //如果该小心没有被注册,则返回
                    if (!_messages[type])
                        return;
                    //定义小心信息
                    var events = {
                            type: type, //消息类型
                            args: args || {} //消息携带数据
                        },
                        i = 0, //消息动作循环变量
                        len = _messages[type].length; //消息动作长度
                    //遍历消息动作
                    for (; i < len; i++) {
                        //依次执行注册的消息对应的动作序列
                        _messages[type][i].call(this, events);
                    }
                },
                //移除信息接口
                remove: function (type, fn) {
                    //如果消息动作队列存在
                    if (_message[type] instanceof Array) {
                        //从最后一个消息动作遍历
                        var i = _message[type].length - 1;
                        for (; i >= 0; i--) {
                            //如果存在该动作在消息动作序列中移除相应动作
                            _messages[type][i] === fn && _messages[type].splice(i, 1);
                        }
                    }
                }
            }
        })();


        function $(id) {
            return document.getElementById(id);
        }

        (function () {
            //增加一则消息
            function addMsgItem(e) {
                var text = e.args.text, //获取消息中用户添加的文本内容
                    ul = $('msg'),
                    li = document.createElement('li'),
                    span = document.createElement('span');
                span.innerHTML = " 关闭"

                li.innerHTML = text;

                span.onclick = function () { //移除留言
                    ul.removeChild(li);
                    Observer.fire('removeCommentMessage', {
                        num: -1
                    });
                }
                li.appendChild(span);
                ul.appendChild(li);
            }
            Observer.regist('addCommentMessage', addMsgItem); //注册添加评论信息
        })();

        (function () {
            function changeMsgNum(e) {
                var num = e.args.num;
                $('msg_num').innerHTML = parseInt($('msg_num').innerHTML) + num;
            }
            Observer.regist('addCommentMessage', changeMsgNum);
            Observer.regist('removeCommentMessage', changeMsgNum);
        })();

        (function () {
            $('user_submit').onclick = function () {

                var text = $('user_input');
                if (text.value === '') {
                    return;
                }
                Observer.fire('addCommentMessage', {
                    text: text.value,
                    num: 1
                });
                text.value = '';
            }
        })();
    </script>
</body>

</html>

在这个例子中可以看出我们将每个模块抽离了出来,互不关系,完美解决模块间耦合功能。
其使用什么广泛,适用于关联于某些行为场景,并触发一系列事件。例如用来发布消息推送、点击事件侦听等等。。。

【论文复现】一种基于价格弹性矩阵的居民峰谷分时电价激励策略【需求响应】(Matlab代码实现)内容概要:本文介绍了一种基于价格弹性矩阵的居民峰谷分时电价激励策略,旨在通过需求响应机制优化电力系统的负荷分布。该研究利用Matlab进行代码实现,构建了居民用电行为与电价变动之间的价格弹性模型,通过分析不同时间段电价调整对用户用电习惯的影响,设计合理的峰谷电价方案,引导用户错峰用电,从而实现电网负荷的削峰填谷,提升电力系统运行效率与稳定性。文中详细阐述了价格弹性矩阵的构建方法、优化目标函数的设计以及求解算法的实现过程,并通过仿真验证了所提策略的有效性。; 适合人群:具备一定电力系统基础知识和Matlab编程能力,从事需求响应、电价机制研究或智能电网优化等相关领域的科研人员及研究生。; 使用场景及目标:①研究居民用电行为对电价变化的响应特性;②设计并仿真基于价格弹性矩阵的峰谷分时电价激励策略;③实现需求响应下的电力负荷优化调度;④为电力公司制定科学合理的电价政策提供理论支持和技术工具。; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,深入理解价格弹性建模与优化求解过程,同时可参考文中方法拓展至其他需求响应场景,如工业用户、商业楼宇等,进一步提升研究的广度与深度。
针对TC275微控制器平台,基于AUTOSAR标准的引导加载程序实现方案 本方案详细阐述了一种专为英飞凌TC275系列微控制器设计的引导加载系统。该系统严格遵循汽车开放系统架构(AUTOSAR)规范进行开发,旨在实现可靠的应用程序刷写与启动管理功能。 核心设计严格遵循AUTOSAR分层软件架构。基础软件模块(BSW)的配置与管理完全符合标准要求,确保了与不同AUTOSAR兼容工具链及软件组件的无缝集成。引导加载程序本身作为独立的软件实体,实现了与上层应用软件的完全解耦,其功能涵盖启动阶段的硬件初始化、完整性校验、程序跳转逻辑以及通过指定通信接口(如CAN或以太网)接收和验证新软件数据包。 在具体实现层面,工程代码重点处理了TC275芯片特有的多核架构与内存映射机制。代码包含了对所有必要外设驱动(如Flash存储器驱动、通信控制器驱动)的初始化与抽象层封装,并设计了严谨的故障安全机制与回滚策略,以确保在软件更新过程中出现意外中断时,系统能够恢复到已知的稳定状态。整个引导流程的设计充分考虑了时序确定性、资源占用优化以及功能安全相关需求,为汽车电子控制单元的固件维护与升级提供了符合行业标准的底层支持。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值