JavaScript观察者模式(经典)
作者:mrr 发布时间:2024-04-22 22:42:05
Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式的概念
Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。
Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。
Observer模式的角色:
Subject(被观察者)
被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。
ConcreteSubject
被观察者的具体实现。包含一些基本的属性状态及其他操作。
Observer(观察者)
接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。
ConcreteObserver
观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。
观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的dom事件. 也是js和dom之间实现的一种观察者模式.
div.onclick = function click (){
alert ( ”click' )
}
只要订阅了div的click事件. 当点击div的时候, function click就会被触发.
那么到底什么是观察者模式呢. 先看看生活中的观察者模式。
好莱坞有句名言. “不要给我打电话, 我会给你打电话”. 这句话就解释了一个观察者模式的来龙去脉。 其中“我”是发布者, “你”是订阅者。
再举个例子,我来公司面试的时候,完事之后每个面试官都会对我说:“请留下你的联系方式, 有消息我们会通知你”。 在这里“我”是订阅者, 面试官是发布者。所以我不用每天或者每小时都去询问面试结果, 通讯的主动权掌握在了面试官手上。而我只需要提供一个联系方式。
观察者模式可以很好的实现2个模块之间的解耦。 假如我正在一个团队里开发一个html5游戏. 当游戏开始的时候,需要加载一些图片素材。加载好这些图片之后开始才执行游戏逻辑. 假设这是一个需要多人合作的项目. 我完成了Gamer和Map模块, 而我的同事A写了一个图片加载器loadImage.
loadImage的代码如下
loadImage( imgAry, function(){
Map.init();
Gamer.init();
} )
当图片加载好之后, 再渲染地图, 执行游戏逻辑. 嗯, 这个程序运行良好. 突然有一天, 我想起应该给游戏加上声音功能. 我应该让图片加载器添上一行代码.
loadImage( imgAry, function(){
Map.init();
Gamer.init();
Sount.init();
} )
可是写这个模块的同事A去了外地旅游. 于是我打电话给他, 喂. 你的loadImage函数在哪, 我能不能改一下, 改了之后有没有副作用. 如你所想, 各种不淡定的事发生了. 如果当初我们能这样写呢:
loadImage.listen( ”ready', function(){
Map.init();
})
loadImage.listen( ”ready', function(){
Gamer.init();
})
loadImage.listen( ”ready', function(){
Sount.init();
})
loadImage完成之后, 它根本不关心将来会发生什么, 因为它的工作已经完成了. 接下来它只要发布一个信号.
loadImage.trigger( ”ready' );
那么监听了loadImage的'ready'事件的对象都会收到通知. 就像上个面试的例子. 面试官根本不关心面试者们收到面试结果后会去哪吃饭. 他只负责把面试者的简历搜集到一起. 当面试结果出来时照着简历上的电话挨个通知.
说了这么多概念, 来一个具体的实现. 实现过程其实很简单. 面试者把简历扔到一个盒子里, 然后面试官在合适的时机拿着盒子里的简历挨个打电话通知结果.
Events = function() {
var listen, log, obj, one, remove, trigger, __this;
obj = {};
__this = this;
listen = function( key, eventfn ) { //把简历扔盒子, key就是联系方式.
var stack, _ref; //stack是盒子
stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = [];
return stack.push( eventfn );
};
one = function( key, eventfn ) {
remove( key );
return listen( key, eventfn );
};
remove = function( key ) {
var _ref;
return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0;
};
trigger = function() { //面试官打电话通知面试者
var fn, stack, _i, _len, _ref, key;
key = Array.prototype.shift.call( arguments );
stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = [];
for ( _i = 0, _len = stack.length; _i < _len; _i++ ) {
fn = stack[ _i ];
if ( fn.apply( __this, arguments ) === false) {
return false;
}
}
return {
listen: listen,
one: one,
remove: remove,
trigger: trigger
}
}
最后用观察者模式来做一个 * 视台的小应用.
//订阅者
var adultTv = Event();
adultTv .listen( ”play', function( data ){
alert ( “今天是谁的电影” + data.name );
});
//发布者
adultTv .trigger( ”play', { ‘name': ‘麻生希' } )


猜你喜欢
- 1.Case函数的用法 (1)使用类似:switch-case与if-else if。 (2)语法: case [字段] when 表达式
- 本文介绍了tf.truncated_normal与tf.random_normal的详细用法,分享给大家,具体如下:tf.truncated
- <title></title> <script src="js/jquery-1.7.2
- 本文实例讲述了Python中的is和id用法。分享给大家供大家参考。具体分析如下:(ob1 is ob2) 等价于 (id(ob1) ==
- 一、http请求的顺序处理方式在高并发场景下,为了降低系统压力,都会使用一种让请求排队处理的机制。本文就介绍在Go中是如何实现的。首先,我们
- 本文对于先前系列文章中实现的C/Python代码统计工具(CPLineCounter),通过C扩展接口重写核心算法加以优化,并与网上常见的统
- 一. torch.stack()函数解析1. 函数说明:1.1 官网:torch.stack(),函数定义及参数说明如下图所示:1.2 函数
- 在看子串匹配问题的时候,书上的关于KMP的算法的介绍总是理解不了。看了一遍代码总是很快的忘掉,后来决定好好分解一下KMP算法,算是给自己加深
- 第一题:ASP中,VBScript的唯一的数据类型是什么?第二题:在ASP中,VBScript有多种控制程序流程语句,如If…Then, S
- python一直对中文支持的不好,最近老遇到编码问题,而且几乎没有通用的方案来解决这个问题,但是对常见的方法都试过之后,发现还是可以解决的,
- 方式一import matplotlib.pyplot as pltimport numpy as npfrom scipy.stats i
- 数据探索性分析(EDA)1. 总览数据概况数据库载入#coding:utf-8#导入warnings包,利用过滤器来实现忽略警告语句。imp
- 一、数组和切片的区别是什么?1.数组数组是内置(build-in)类型,是一组同类型数据的集合,它是值类型,通过从0开始的下标索引访问元素值
- 在用python绘图的时候,经常由于数据的原因导致画出来的图折线分界过于明显,因此需要对原数据绘制的折线进行平滑处理,本文介绍利用插值法进行
- 目录一、conftest.py的特点二、conftest.py的使用场景三、conftest.py的生效范围四、conftest.py的的s
- 一、MySQL进阶查询首先先创建两张表mysql -u root -pXXX #登陆数据库,XXX为密码crea
- 废话不多说 上语句:查询锁表语句:select object_name,machine,s.sid,s.serial#from v$lock
- 本文实例讲述了Python使用itchat模块实现简单的微信控制电脑功能。分享给大家供大家参考,具体如下:#!/usr/bin/python
- 本文实例讲述了Python爬虫之pandas基本安装与使用方法。分享给大家供大家参考,具体如下:一、简介:Python Data Analy
- 修改镜像源的原因是pip和conda默认国外镜像源,所以每次安装模块pip install ×××或者 conda install ×××的