观察者模式

通过创建一个可观察的对象,当发生一个感兴趣的事件时将该事件通告给所有观察者,从而形成松散的耦合

订阅杂志

//发布者对象
var publisher = {
subscribers: {
any: [] //事件类型
},
//将订阅者添加到subscribers数组;
subscribe: function(fn, type) {
type = type || 'any';
if(typeof this.subscribers[type] === 'undefined') {
this.subscribers[type] = [];
}
this.subscribers[type].push(fn);
},
//从订阅者数组中删除订阅者
unsubscribe: function(fn, type) {
this.visitSubscribers('publish', publication, type);
},
//遍历循环
publish: function(publication, type) {
this.visitSubscribers('publish', publication, type);
},
visitSubscribers: function(action, arg, type) {
var pubtype = type || 'any',
subscribers = this.subscribers[pubtype], i, max = subscribers.length;
for(i = 0; i < max; i++) {
if(action === 'publish') {
subscribers[i](arg);
} else {
if(subscribers[i] === arg) {
subscribers.splice(i, 1);
}
}
}
}
}
//构造发行者
function makePublisher(o) {
var i;
for(i in publisher) {
if(publisher.hasOwnProperty(i) && typeof publisher[i] === 'function') {
o[i] = publisher[i];
}
}
o.subscribers = {any: []};
}
//paper对象,发布日刊和月刊
var paper = {
daily: function() {
this.publish("big news today");
},
monthly: function() {
this.publish("interesting analysis", "monthly");
}
};
//订阅者joe
var joe = {
drinkCoffee: function(paper) {
console.log('Just read ' + paper);
},
sundayPreNap: function(monthly) {
console.log('About to fall asleep reading this ' + monthly);
}
}
//将paper构造成一个发行者
makePublisher(paper);
//joe订阅paper
paper.subscribe(joe.drinkCoffee);
paper.subscribe(joe.sundayPreNap, 'monthly');
//触发事件
paper.daily();
paper.daily();
paper.daily();
paper.monthly();
//扩展将joe为发布者
makePublisher(joe);
joe.tweet = function(msg) {
this.publish(msg);
}
paper.readTweets = function(tweet) {
alert('Call big meeting! Someone ' + tweet);
}
joe.subscribe(paper.readTweets); joe.tweet('hated the paper today');

按键游戏

var publisher = {
subscribers: {
any: []
},
on: function (type, fn, context) {
type = type || 'any';
fn = typeof fn === "function" ? fn : context[fn];
if (typeof this.subscribers[type] === "undefined") {
this.subscribers[type] = [];
}
this.subscribers[type].push({fn: fn, context: context || this});
},
remove: function (type, fn, context) {
this.visitSubscribers('unsubscribe', type, fn, context);
},
fire: function (type, publication) {
this.visitSubscribers('publish', type, publication);
},
visitSubscribers: function (action, type, arg, context) {
var pubtype = type || 'any',
subscribers = this.subscribers[pubtype], i,
max = subscribers ? subscribers.length : 0; for (i = 0; i < max; i += 1) {
if (action === 'publish') {
subscribers[i].fn.call(subscribers[i].context, arg);
} else {
if (subscribers[i].fn === arg && subscribers[i].context === context) {
subscribers.splice(i, 1);
}
}
}
}
}; function makePublisher(o) {
var i;
for (i in publisher) {
if (publisher.hasOwnProperty(i) && typeof publisher[i] === "function") {
o[i] = publisher[i];
}
}
o.subscribers = {any: []};
} var game = {
keys: {},
addPlayer: function (player) {
var key = player.key.toString().charCodeAt(0);
this.keys[key] = player;
},
handleKeypress: function (e) {
e = e || window.event; // IE
if (game.keys[e.which]) {
game.keys[e.which].play();
}
},
handlePlay: function (player) {
var i, players = this.keys, score = {};
for (i in players) {
if (players.hasOwnProperty(i)) {
score[players[i].name] = players[i].points;
}
}
this.fire('scorechange', score);
}
}; function Player(name, key) {
this.points = 0;
this.name = name;
this.key = key;
this.fire('newplayer', this);
} Player.prototype.play = function () {
this.points += 1;
this.fire('play', this);
}; var scoreboard = {
element: document.getElementById('results'),
update: function (score) {
var i, msg = '';
for (i in score) {
if (score.hasOwnProperty(i)) {
msg += '<p><strong>' + i + '<\/strong>: ';
msg += score[i];
msg += '<\/p>';
}
}
this.element.innerHTML = msg;
}
}; makePublisher(Player.prototype);
makePublisher(game); Player.prototype.on("newplayer", "addPlayer", game);
Player.prototype.on("play", "handlePlay", game); game.on("scorechange", scoreboard.update, scoreboard); window.onkeypress = game.handleKeypress; var playername, key;
while (1) {
playername = prompt("Add player (name)");
if (!playername) {
break;
}
while (1) {
key = prompt("Key for " + playername + "?");
if (key) {
break;
}
}
new Player(playername, key);
}

javascript优化--12模式(设计模式)03的更多相关文章

  1. javascript优化--11模式(设计模式)02

    策略模式 在选择最佳策略以处理特定任务(上下文)的时候仍然保持相同的接口: //表单验证的例子 var data = { firs_name: "Super", last_name ...

  2. javascript优化--10模式(设计模式)01

    单体模式:保证一个特定类仅有一个实例;即第二次使用同一个类创建新对象时,应该得到与第一个所创建对象完全相同对象: 在JS中,可以认为每次在使用对象字面量创建对象的时候,实际上就在创建一个单体: 当使用 ...

  3. javascript优化--13模式1(DOM和浏览器模式)

    注意分离: 通过将CSS关闭来测试页面是否仍然可用,内容是否依然可读: 将JavaScript关闭来测试页面仍然可以执行正常功能:所有连接是否正常工作:所有的表单是否可以正常工作: 不使用内联处理器( ...

  4. javascript优化--08模式(代码复用)01

    优先使用对象组合,而不是类继承: 类式继承:通过构造函数Child()来获取来自于另一个构造函数Parent()的属性: 默认模式:子类的原型指向父类的一个实例 function inherit(C, ...

  5. javascript优化--06模式(对象)01

    命名空间: 优点:可以解决命名混乱和第三方冲突: 缺点:长嵌套导致更长的查询时间:更多的字符: 通用命名空间函数: var MYAPP = MYAPP || {}; MYAPP.namespace = ...

  6. javascript优化--05模式(函数)

    回调函数模式: 基本例子: var findNodes = function (callback) { ...................... if (typeof callback !== ' ...

  7. javascript优化--14模式2(DOM和浏览器模式)

    远程脚本 XMLHttpRequest JSONP 和XHR不同,它不受同域的限制: JSONP请求的可以是任意的文档: 请求的URL通常格式为http://example.js?calback=Ca ...

  8. javascript优化--09模式(代码复用)02

    原型继承 ://现代无类继承模式 基本代码: var parent = { name : "Papa" } var child = object(parent); function ...

  9. javascript优化--07模式(对象)02

    沙箱模式: 解决空间命名模式的几个缺点: 命名空间模式中无法同时使用一个应用程序或库的两个版本运行在同一个页面中,因为两者需要相同的全局符号: 以点分割,需要输入更长的字符,解析时间也更长: 全局构造 ...

随机推荐

  1. asp.net 图片下载

    string fileName = "123.jpg";//图片名字                    string filePath = Server.MapPath(&qu ...

  2. Python简易聊天工具-基于异步Socket通信

    继续学习Python中,最近看书<Python基础教程>中的虚拟茶话会项目,觉得很有意思,自己敲了一遍,受益匪浅,同时记录一下. 主要用到异步socket服务客户端和服务器模块asynco ...

  3. ios cell展示可滑动的图片

    需求: 点击cell上的图片.图片以原图显示出来,可以放大或缩小.再次点击图片移除图片显示原来界面.(和QQ空间看图片类似) 点击图片实现效果: 1. 自定义一个 UITableView (KDIma ...

  4. xmpp即时通讯的笔记(摘抄)

    xmpp的使用: 即时通讯 instant messaging(IM) :  -->实时收发信息! 即时通讯相关软件: **QQ,MSN,GoogleTalk,AIM,Jabber(XMPP别名 ...

  5. 优化MyBatis配置文件中的配置

    一.为实体类定义别名,简化sql映射xml文件中的引用 之前,我们在sql映射xml文件中的引用实体类时,需要写上实体类的全类名(包名+类名),如下: <!-- 创建用户(Create) --& ...

  6. Jmeter 中使用非GUI启动进行压力测试

    使用非 GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资源.使用命令jmeter -n -t <testplan filename> -l <list ...

  7. WPF控件

    1:内容控件(Content Controls)2:条目控件(Items Controls)3:文本控件(Text Controls)4:范围控件(Range Controls) 一:内容控件 内容控 ...

  8. 微信token验证失败的解决方法

    一.问题由来 在使用URL和Token启用微信公众平台开发模式消息接口的时候,我们会碰到下面三种情况 1. token校验失败 这样回头检查一下各项配置是否正确.如果确定配置没有问题,请按下面的方法检 ...

  9. [LeetCode] Ugly Number

    Ugly Number Total Accepted: 20760 Total Submissions: 63208 Difficulty: Easy Write a program to check ...

  10. .net socket 层面实现代理服务器

    socket 层面实现代理服务器 首先是简一个简单的socket客户端和服务器端的例子 建立连接 Socket client = new Socket(AddressFamily.InterNetwo ...