策略模式

在选择最佳策略以处理特定任务(上下文)的时候仍然保持相同的接口;

//表单验证的例子
var data = {
firs_name: "Super",
last_name: "Man",
age: "unknown",
username: "o_0"
} validator = {
types: {},
message: [],
config: {},
validate: function(data) {
var i, msg, type, checker, result_ok;
this.message = [];
for(i in data) {
if(data.hasOwnProperty(i)) {
type = this.config[i];
checker = this.types[type];
if(!type) continue;
if(!checker) {
throw {
name: "ValidationError",
message: "No handler to validate type " + type
};
}
result_ok = checker.validate(data[i]);
if(!result_ok) {
msg = "Invalid value for *" + i + "*, " + checker.instructions;
this.message.push(msg);
}
}
}
return this.hasErrors();
},
//帮助程序
hasErrors: function() {
return this.message.length !== 0;
}
} validator.config = {
firs_name: 'isNonEmpty',
age: 'isNumber',
username: 'isAlphaNum'
} validator.types = {
isNonEmpty: {
validate: function (value) {
return value !== "";
},
instructions: "this value cannot be empty"
},
isNumber: {
validate: function(value) {
return !isNaN(value);
},
instructions: "the value can only be a valid number, e.g. 1, 3.14 or 2010"
},
isAlphaNum: {
validate: function(value) {
return !/[^a-z0-9]/i.test(value);
},
instructions: "the value can only contain characters and number, no special symbols"
}
} validator.validate(data); if(validator.hasErrors()) {
console.log(validator.message.join('\n'));
}

外观模式

通过把常用方法包装到一个新的方法中,从而提供一个更为便利的API

//以处理浏览器事件为例
var myevent = {
//...
stop: function(e) {
(typeof e.preventDefault === 'function') && e.preventDefault();
(typeof e.stopPropagation === 'function') && e.stopPropagation();
//ie
(typeof e.returnVlaue === 'boolean') && (e.returnVlaue = false);
(typeof e.cancelBubble === 'boolean') && (e.cancelBubble = true);
}
}

代理模式

通过包装一个对象以控制对它的访问,其主要方法是将访问聚集为组成或仅当真正必要的时候才执行访问,从而避免了高昂的操作开销

这种模式的其中一个例子为:延迟初始化;假设初始化对象开销非常大,但客户端可能在初始化对象后从未使用它,这种时候就可以通过代理替换本体对象的接口来解决

  • 首先由客户端发出一个初始化请求,然后代理以一切正常作为响应
  • 但实际上却没有将该消息传递到本体对象;
  • 直到客户端明显需要本体对象完成一些工作的时候,代理财经两个消息一起传递;
//视频列表例子
<p><span id="toggle-all">Toggle Checked</span></p>
<ol id="vids">
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2158073">Gravedigger</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--4472739">Save Me</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--45286339">Grush</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2144530">Don't Drink The Water</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--217241800">Funny the Way It Is</a></li>
<li><input type="checkbox" checked><a href="http://new.music.yahoo.com/vides/--2144532">What Would You Say</a></li>
</ol>
//未使用代理
var http = {
makeRequest: function(ids, callback) {
var url = 'http://query.yahooapis.com/v1/public/yql?q=',
sql = 'select * from music.video.id where ids IN ("%ID%")',
format = "format=json",
handler = "callback=" + callback,
script = document.createElement('script')
sql = sql.replace("%ID%", ids.join('","'));
sql = encodeURIComponent(sql);
url += sql + '&' + format + '&' + handler;
script.src = url;
document.body.appendChild(script);
}
}
var videos = {
getPlayer: function(id) {},
updateList: function(data) {},
//展开折叠信息区域
getInfo: function(id) {
var info = $("info" + id);
if(!info) {
//负责与服务器通信
http.makeRequest([id], "videos.updateList");
return;
}
if(info.style.display === "none") {
info.style.display = '';
} else {
info.style.display = 'none';
}
}
}; var $ = function (id) {
return document.getElementById(id);
};
$("vids").onclick = function(e) {
var scr ,id;
e = e || window.event;
src = e.target || e.srcElement;
//阻止跳转
if(src.nodeName !== "A") return;
if(typeof e.preventDefault === "function") e.preventDefault();
e.returnValue = false;
id = src.href.split('--')[1];
//如果是正在播放,即已经展开
if(src.className == "play") {
src.parentNode.innerHTML = videos.getPlayer(id);
return;
}
src.parentNode.id = "v" + id;
videos.getInfo(id);
}; $("toggle-all").onclick = function(e) {
var hrefs, i, max, id;
hrefs = $('vids').getElementsByTagName('a');
for(i = 0, max = hrefs.length; i < max; i += 1) {
if(hrefs[i].className === "play") continue;
if(!hrefs[i].parentNode.firstChild.checked) continue;
id = hrefs[i].href.split('--')[1];
hrefs[i].parentNode.id = '\/' + id;
videos.getInfo(id);
}
}
//使用代理:就只是将http.makeRequest()改为proxy.makeRequest(); var proxy = {
ids: [],
delay: 50,
timeout: null,
callback: null,
context: null,
makeRequest: function(id, callback, context) {
//加入列队
this.ids.push(id);
this.callback = callback || function(){};
this.context = context || '';
//设置超时时间
if(!this.timeout) {
this.timeout = setTimeout(function() {
proxy.flush();
}, this.delay);
}
},
flush: function() {
http.makeRequest(this.ids, 'proxy.handler');
//清除超时设置和列队
this.timeout = null;
this.ids = [];
},
handler: function(data) {
var i, max;
//单个视频
if(data.error) return;
if(parseInt(data.query.count, 10) === 1) {
proxy.callback.call(proxy.context, data.query.results.Video);
return;
}
//多个视频
for( i = 0, max = data.query.results.Video.length; i < max; i++) {
proxy.callback.call(proxy.context, data.query.results.Video[i]);
}
}
}

缓存代理

代理可以通过将以前的请求结果缓存到新的cache属性中,从而更进一步地保护本体对象http地访问;那么如果videos对象恰好再一次请求同一个视频id,proxy可以直接从缓存中取出该信息

中介者模式

通过使对象之间相互并不直接‘通话’,而是仅通过一个中介者对象进行通信,从而促进形成松散耦合

<p>Player one press "1", player two press "0". Go! (you have half a minute...)</p>
<div id="results"></div>
//
//玩家
function Player(name) {
this.points = 0;
this.name = name;
}
Player.prototype.play = function () {
this.points += 1;
//中介者的played方法在play调用后,更新score哈希表并传送到记分板
mediator.played();
};
//记分板
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;
}
};
//中介者
var mediator = {
players: {},
setup: function () {
var players = this.players;
players.home = new Player('Home');
players.guest = new Player('Guest');
},
played: function () {
var players = this.players,
score = {
Home: players.home.points,
Guest: players.guest.points
};
scoreboard.update(score);
},
keypress: function (e) {
e = e || window.event; // IE
if (e.which === 49) { // key "1"
mediator.players.home.play();
return;
}
if (e.which === 48) { // key "0"
mediator.players.guest.play();
return;
}
}
};
//初始化中介者
mediator.setup();
window.onkeypress = mediator.keypress;
//30s
setTimeout(function () {
window.onkeypress = null;
alert('Game over!');
}, 30000);

其中记分板与玩家对象并不关联,通过中介者沟通

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

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

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

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

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

  3. javascript优化--12模式(设计模式)03

    观察者模式 通过创建一个可观察的对象,当发生一个感兴趣的事件时将该事件通告给所有观察者,从而形成松散的耦合 订阅杂志 //发布者对象 var publisher = { subscribers: { ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Java实现注册邮箱激活验证

    邮件发送servelet实现 package com.xbs.register.main; import java.io.IOException;import java.util.Date;impor ...

  2. 【leetcode】Excel Sheet Column Title & Excel Sheet Column Number (easy)

    Given a positive integer, return its corresponding column title as appear in an Excel sheet. For exa ...

  3. [Android Pro] 通过包名启动应用

    Intent intent = packageManager.getLaunchIntentForPackage(WEIXIN_PKGNAME); intent.setFlags(Intent.FLA ...

  4. Express 4 中如何使用connect-mongo

    正在跟随上面的教程一步一步做,在会话支持那一节中安装 connect-mongo 后,添加: var MongoStore = require('connect-mongo')(express); v ...

  5. 已有a,b两个链表,每个链表中的结点包括学号,成绩。要求把两个链表合并。按学号升序排列.

    #include <stdio.h>#define SIZE sizeof(struct student)struct student{       long num;       flo ...

  6. java ---线程wait/notify/sleep/yield/join

    一.线程的状态 Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态). New:新建状态,当线 ...

  7. 关于安装Ubuntu后触摸板无法使用的解决方案

    安装了Ubuntu后发现触摸板无法使用,以为是修改了安装文件导致(之前拿安装源文件做了小实验),于是重装,之后触摸板仍无法使用,在一个长满小广告的页面上找到了解决方案. 以下是原文章内容: 最近突然发 ...

  8. 三、jQuery--jQuery基础--jQuery基础课程--第8章 jQuery 实现Ajax应用

    1.使用load()方法异步请求数据 使用load()方法通过Ajax请求加载服务器中的数据,并把返回的数据放置到指定的元素中,它的调用格式为:load(url,[data],[callback]) ...

  9. python中random模块使用

  10. Pyqt 时时CPU使用情况

    借鉴代码来自:https://github.com/hgoldfish/quickpanel 实现代码: # -*- coding:utf-8 -*- from __future__ import p ...